New CDI based EE injection manager incubating implementation. (#4822)
* New CDI based EE injection manager incubating implementation.
Signed-off-by: jansupol <jan.supol@oracle.com>
diff --git a/incubator/cdi-inject-weld/pom.xml b/incubator/cdi-inject-weld/pom.xml
new file mode 100644
index 0000000..44b60b7
--- /dev/null
+++ b/incubator/cdi-inject-weld/pom.xml
@@ -0,0 +1,148 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ Copyright (c) 2017, 2021 Oracle and/or its affiliates. All rights reserved.
+
+ This program and the accompanying materials are made available under the
+ terms of the Eclipse Public License v. 2.0, which is available at
+ http://www.eclipse.org/legal/epl-2.0.
+
+ This Source Code may also be made available under the following Secondary
+ Licenses when the conditions for such availability set forth in the
+ Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ version 2 with the GNU Classpath Exception, which is available at
+ https://www.gnu.org/software/classpath/license.html.
+
+ SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+
+-->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>org.glassfish.jersey.incubator</groupId>
+ <artifactId>project</artifactId>
+ <version>2.35-SNAPSHOT</version>
+ </parent>
+
+ <artifactId>jersey-cdi-inject-weld</artifactId>
+ <packaging>jar</packaging>
+ <name>jersey-inject-cdi-weld</name>
+
+ <description>CDI InjectionManager implementation</description>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.glassfish.jersey.core</groupId>
+ <artifactId>jersey-common</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.glassfish.jersey.core</groupId>
+ <artifactId>jersey-client</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.glassfish.jersey.core</groupId>
+ <artifactId>jersey-server</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+
+ <dependency>
+ <groupId>org.glassfish.jersey.containers</groupId>
+ <artifactId>jersey-container-servlet-core</artifactId>
+ <version>${project.version}</version>
+ <scope>provided</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>jakarta.servlet</groupId>
+ <artifactId>jakarta.servlet-api</artifactId>
+ <version>${servlet4.version}</version>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.glassfish.jersey.containers</groupId>
+ <artifactId>jersey-container-grizzly2-http</artifactId>
+ <version>${project.version}</version>
+ <scope>provided</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>jakarta.enterprise</groupId>
+ <artifactId>jakarta.enterprise.cdi-api</artifactId>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.jboss.weld.se</groupId>
+ <artifactId>weld-se-core</artifactId>
+ <scope>provided</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>junit</groupId>
+ <artifactId>junit</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>jakarta.el</groupId>
+ <artifactId>jakarta.el-api</artifactId>
+ <scope>test</scope>
+ </dependency>
+ </dependencies>
+
+ <build>
+ <resources>
+ <resource>
+ <directory>src/main/resources</directory>
+ <filtering>true</filtering>
+ </resource>
+ </resources>
+
+ <plugins>
+ <plugin>
+ <groupId>com.sun.istack</groupId>
+ <artifactId>istack-commons-maven-plugin</artifactId>
+ <inherited>true</inherited>
+ </plugin>
+ <plugin>
+ <groupId>org.codehaus.mojo</groupId>
+ <artifactId>build-helper-maven-plugin</artifactId>
+ <inherited>true</inherited>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.felix</groupId>
+ <artifactId>maven-bundle-plugin</artifactId>
+ <inherited>true</inherited>
+ <extensions>true</extensions>
+ <configuration>
+ <instructions>
+ <Export-Package>
+ org.glassfish.jersey.inject.weld.managed.*;version=${project.version}
+ </Export-Package>
+ <Import-Package>
+ sun.misc.*;resolution:=optional,
+ ${jakarta.annotation.osgi.version},
+ *
+ </Import-Package>
+ </instructions>
+ <unpackBundle>true</unpackBundle>
+ </configuration>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-jar-plugin</artifactId>
+ <executions>
+ <execution>
+ <id>default-jar</id>
+ <phase>package</phase>
+ <goals>
+ <goal>jar</goal>
+ </goals>
+ </execution>
+ </executions>
+ </plugin>
+ </plugins>
+ </build>
+</project>
diff --git a/incubator/cdi-inject-weld/src/main/java/org/glassfish/jersey/inject/weld/internal/bean/BeanHelper.java b/incubator/cdi-inject-weld/src/main/java/org/glassfish/jersey/inject/weld/internal/bean/BeanHelper.java
new file mode 100644
index 0000000..d1fbafa
--- /dev/null
+++ b/incubator/cdi-inject-weld/src/main/java/org/glassfish/jersey/inject/weld/internal/bean/BeanHelper.java
@@ -0,0 +1,420 @@
+/*
+ * Copyright (c) 2021 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.inject.weld.internal.bean;
+
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Method;
+import java.util.Collection;
+import java.util.List;
+import java.util.function.Supplier;
+
+import javax.enterprise.inject.spi.AfterBeanDiscovery;
+import javax.enterprise.inject.spi.AnnotatedType;
+import javax.enterprise.inject.spi.Bean;
+import javax.enterprise.inject.spi.BeanManager;
+import javax.enterprise.inject.spi.InjectionTarget;
+import javax.ws.rs.HttpMethod;
+import javax.ws.rs.Path;
+import javax.ws.rs.RuntimeType;
+
+import org.glassfish.jersey.inject.weld.internal.data.BindingBeanPair;
+import org.glassfish.jersey.inject.weld.internal.inject.InitializableInstanceBinding;
+import org.glassfish.jersey.inject.weld.internal.inject.InitializableSupplierInstanceBinding;
+import org.glassfish.jersey.inject.weld.internal.injector.CachedConstructorAnalyzer;
+import org.glassfish.jersey.inject.weld.internal.injector.InjectionUtils;
+import org.glassfish.jersey.inject.weld.internal.injector.JerseyConstructorInjectionPoint;
+import org.glassfish.jersey.inject.weld.internal.injector.JerseyInjectionTarget;
+import org.glassfish.jersey.inject.weld.internal.injector.JerseyTwofoldInstantiator;
+import org.glassfish.jersey.inject.weld.internal.injector.WrappingJerseyInjectionTarget;
+import org.glassfish.jersey.internal.inject.ClassBinding;
+import org.glassfish.jersey.internal.inject.InjectionResolver;
+import org.glassfish.jersey.internal.inject.PerThread;
+import org.glassfish.jersey.internal.inject.SupplierClassBinding;
+
+import org.jboss.weld.annotated.enhanced.EnhancedAnnotatedConstructor;
+import org.jboss.weld.annotated.enhanced.EnhancedAnnotatedType;
+import org.jboss.weld.annotated.enhanced.jlr.ConstructorSignatureImpl;
+import org.jboss.weld.annotated.enhanced.jlr.EnhancedAnnotatedTypeImpl;
+import org.jboss.weld.annotated.slim.SlimAnnotatedType;
+import org.jboss.weld.bean.builtin.BeanManagerProxy;
+import org.jboss.weld.injection.ConstructorInjectionPoint;
+import org.jboss.weld.injection.producer.AbstractInstantiator;
+import org.jboss.weld.injection.producer.BasicInjectionTarget;
+import org.jboss.weld.injection.producer.BeanInjectionTarget;
+import org.jboss.weld.injection.producer.InjectionTargetService;
+import org.jboss.weld.injection.producer.Instantiator;
+import org.jboss.weld.injection.producer.NonProducibleInjectionTarget;
+import org.jboss.weld.manager.BeanManagerImpl;
+import org.jboss.weld.resources.ClassTransformer;
+
+/**
+ * Helper class to register a {@link Bean} into CDI {@link BeanManager}.
+ */
+public abstract class BeanHelper {
+
+ /**
+ * Forbids the creation of {@link BeanHelper} instance.
+ */
+ private BeanHelper() {
+ }
+
+ /**
+ * Registers an instance as {@link JerseyBean} into {@link BeanManager}.
+ *
+ * @param binding object containing {@link javax.enterprise.inject.spi.BeanAttributes} information.
+ * @param abd {@link AfterBeanDiscovery} event.
+ * @param resolvers all registered injection resolvers.
+ * @param <T> type of the instance which is registered.
+ */
+ public static <T> void registerBean(RuntimeType runtimeType, InitializableInstanceBinding<T> binding, AfterBeanDiscovery abd,
+ List<InjectionResolver> resolvers, BeanManager beanManager) {
+ InitializableInstanceBean<T> bean = new InitializableInstanceBean<>(runtimeType, binding);
+ /*
+ * Wrap into custom injection target that is able to inject the additional @Inject, @Context, @*Param fields into
+ * the given service.
+ */
+ InjectionTarget<T> injectionTarget = new WrappingJerseyInjectionTarget<>(bean, resolvers);
+ bean.setInjectionTarget(injectionTarget);
+ abd.addBean(bean);
+ }
+
+ /**
+ * Registers a class as {@link JerseyBean} into {@link BeanManager}.
+ *
+ * @param binding object containing {@link javax.enterprise.inject.spi.BeanAttributes} information.
+ * @param abd {@link AfterBeanDiscovery} event.
+ * @param resolvers all registered injection resolvers.
+ * @param beanManager currently used bean manager.
+ * @param <T> type of the class which is registered.
+ */
+ public static <T> BindingBeanPair registerBean(RuntimeType runtimeType, ClassBinding<T> binding, AfterBeanDiscovery abd,
+ Collection<InjectionResolver> resolvers, BeanManager beanManager) {
+ AnnotatedType<T> annotatedType = beanManager.createAnnotatedType(binding.getService());
+ InjectionTarget<T> injectionTarget = beanManager.createInjectionTarget(annotatedType);
+
+ ClassBean<T> bean = new ClassBean<>(runtimeType, binding);
+ bean.setInjectionTarget(getJerseyInjectionTarget(binding.getService(), injectionTarget, bean, resolvers));
+ abd.addBean(bean);
+
+ return new BindingBeanPair(binding, bean);
+ }
+
+ /**
+ * Registers an instance supplier and its provided value as {@link JerseyBean}s into {@link BeanManager}.
+ *
+ * @param binding object containing {@link javax.enterprise.inject.spi.BeanAttributes} information.
+ * @param abd {@link AfterBeanDiscovery} event.
+ * @param <T> type of the instance which is registered.
+ */
+ public static <T> void registerSupplier(RuntimeType runtimeType, InitializableSupplierInstanceBinding<T> binding,
+ AfterBeanDiscovery abd, BeanManager beanManager) {
+ /*
+ * CDI does not provide sufficient support for ThreadScoped Supplier
+ */
+ if (binding.getScope() == PerThread.class) {
+ BeanManagerImpl manager;
+ if (beanManager instanceof BeanManagerProxy) {
+ manager = ((BeanManagerProxy) beanManager).unwrap();
+ } else {
+ manager = (BeanManagerImpl) beanManager;
+ }
+ abd.addBean(new InitializableSupplierThreadScopeBean(runtimeType, binding, manager));
+ } else {
+ abd.addBean(new InitializableSupplierInstanceBean<>(runtimeType, binding));
+ abd.addBean(new InitializableSupplierInstanceBeanBridge<>(runtimeType, binding));
+ }
+ }
+
+ /**
+ * Registers a class supplier and its provided value as {@link JerseyBean}s into {@link BeanManager}.
+ *
+ * @param binding object containing {@link javax.enterprise.inject.spi.BeanAttributes} information.
+ * @param abd {@link AfterBeanDiscovery} event.
+ * @param resolvers all registered injection resolvers.
+ * @param beanManager currently used bean manager.
+ * @param <T> type of the class which is registered.
+ */
+ @SuppressWarnings("unchecked")
+ public static <T> BindingBeanPair registerSupplier(RuntimeType runtimeType, SupplierClassBinding<T> binding,
+ AfterBeanDiscovery abd, Collection<InjectionResolver> resolvers, BeanManager beanManager) {
+
+ Class<Supplier<T>> supplierClass = (Class<Supplier<T>>) binding.getSupplierClass();
+ AnnotatedType<Supplier<T>> annotatedType = beanManager.createAnnotatedType(supplierClass);
+ InjectionTarget<Supplier<T>> injectionTarget = beanManager.createInjectionTarget(annotatedType);
+
+ SupplierClassBean<T> supplierBean = new SupplierClassBean<>(runtimeType, binding);
+ InjectionTarget<Supplier<T>> jit = getJerseyInjectionTarget(supplierClass, injectionTarget, supplierBean, resolvers);
+ supplierBean.setInjectionTarget(jit);
+
+ final SupplierBeanBridge supplierBeanBridge = new SupplierBeanBridge(runtimeType, binding, beanManager);
+
+ abd.addBean(supplierBean);
+ abd.addBean(supplierBeanBridge);
+
+ return new BindingBeanPair(binding, supplierBean, supplierBeanBridge);
+ }
+
+ /**
+ * Update ClassBinding Bean by {@link ConstructorInjectionPoint} for the client side beans.
+ * @param binding The ClassBinding used to create a client side ConstructorInjectionPoint.
+ * @param pair {@link BindingBeanPair} that contains the original server side Bean.
+ * @param resolvers Resolvers handling Jersey specific injection annotations.
+ * @param beanManager The {@link BeanManager}.
+ */
+ public static void updateBean(ClassBinding binding,
+ BindingBeanPair pair, Collection<InjectionResolver> resolvers, BeanManager beanManager) {
+
+ final JerseyBean bean = pair.getBeans().get(0);
+ final ConstructorInjectionPoint cip = createConstructorInjectionPoint(binding, bean, resolvers, beanManager);
+
+ if (ClassBean.class.isInstance(bean)
+ && JerseyInjectionTarget.class.isInstance(((ClassBean) bean).getInjectionTarget())) {
+ final JerseyTwofoldInstantiator instantiator =
+ ((JerseyInjectionTarget) ((ClassBean) bean).getInjectionTarget()).getTwofoldInstantiator();
+ instantiator.setOptionalConstructorInjectionPoint(cip);
+ }
+ }
+
+ /**
+ * Update SupplierClassBinding Bean by {@link ConstructorInjectionPoint} for the client side beans.
+ * @param binding The SupplierClassBinding used to create a client side ConstructorInjectionPoint.
+ * @param pair {@link BindingBeanPair} that contains the original server side Bean.
+ * @param resolvers Resolvers handling Jersey specific injection annotations.
+ * @param beanManager The {@link BeanManager}.
+ */
+ public static void updateSupplierBean(SupplierClassBinding binding,
+ BindingBeanPair pair, Collection<InjectionResolver> resolvers, BeanManager beanManager) {
+
+ final JerseyBean bean = pair.getBeans().get(0);
+ final ConstructorInjectionPoint cip = createConstructorInjectionPoint(binding, bean, resolvers, beanManager);
+
+ if (SupplierClassBean.class.isInstance(bean)
+ && JerseyInjectionTarget.class.isInstance(((SupplierClassBean) bean).getInjectionTarget())) {
+ final JerseyTwofoldInstantiator instantiator =
+ ((JerseyInjectionTarget) ((SupplierClassBean) bean).getInjectionTarget()).getTwofoldInstantiator();
+ instantiator.setOptionalConstructorInjectionPoint(cip);
+ }
+ }
+
+ private static <T> ConstructorInjectionPoint<T> createConstructorInjectionPoint(
+ SupplierClassBinding<T> binding, Bean<T> bean, Collection<InjectionResolver> resolvers, BeanManager beanManager) {
+
+ final Class<Supplier<T>> bindingClass = (Class<Supplier<T>>) binding.getSupplierClass();
+ final AnnotatedType<Supplier<T>> annotatedType = beanManager.createAnnotatedType(bindingClass);
+ final InjectionTarget<Supplier<T>> injectionTarget = beanManager.createInjectionTarget(annotatedType);
+
+ final CachedConstructorAnalyzer<Supplier<T>> analyzer =
+ new CachedConstructorAnalyzer<>(bindingClass, InjectionUtils.getInjectAnnotations(resolvers));
+
+ if (analyzer.hasCompatibleConstructor()) {
+ EnhancedAnnotatedConstructor<T> constructor = createEnhancedAnnotatedType((BasicInjectionTarget) injectionTarget)
+ .getDeclaredEnhancedConstructor(new ConstructorSignatureImpl(analyzer.getConstructor()));
+
+ JerseyConstructorInjectionPoint<T> constructorInjectionPoint = new JerseyConstructorInjectionPoint<T>(
+ constructor, bean, ((BasicInjectionTarget) injectionTarget).getBeanManager(), resolvers);
+ return constructorInjectionPoint;
+ }
+ return null;
+ }
+
+ private static <T> ConstructorInjectionPoint<T> createConstructorInjectionPoint(
+ ClassBinding<T> binding, Bean<T> bean, Collection<InjectionResolver> resolvers, BeanManager beanManager) {
+
+ final Class<T> bindingClass = binding.getImplementationType();
+ final AnnotatedType<T> annotatedType = beanManager.createAnnotatedType(bindingClass);
+ final InjectionTarget<T> injectionTarget = beanManager.createInjectionTarget(annotatedType);
+
+ final CachedConstructorAnalyzer<T> analyzer =
+ new CachedConstructorAnalyzer<>(bindingClass, InjectionUtils.getInjectAnnotations(resolvers));
+
+ if (analyzer.hasCompatibleConstructor()) {
+ EnhancedAnnotatedConstructor<T> constructor = createEnhancedAnnotatedType((BasicInjectionTarget) injectionTarget)
+ .getDeclaredEnhancedConstructor(new ConstructorSignatureImpl(analyzer.getConstructor()));
+
+ JerseyConstructorInjectionPoint<T> constructorInjectionPoint = new JerseyConstructorInjectionPoint<T>(
+ constructor, bean, ((BasicInjectionTarget) injectionTarget).getBeanManager(), resolvers);
+ return constructorInjectionPoint;
+ }
+ return null;
+ }
+
+ private static <T> InjectionTarget<T> getJerseyInjectionTarget(Class<T> clazz, InjectionTarget<T> injectionTarget,
+ Bean<T> bean, Collection<InjectionResolver> resolvers) {
+ BasicInjectionTarget<T> it = (BasicInjectionTarget<T>) injectionTarget;
+
+ /*
+ * Looks at whether the DefaultInstantiator resolving a valid constructor does not met this case:
+ * - No constructor with @Inject annotation is defined
+ * - NoArgs constructor is defined
+ * - Instantiator ignores JAX-RS valid constructor with multiple params
+ */
+ boolean noArgConstructor = isNoArgConstructorCase(it, clazz);
+
+ JerseyInjectionTarget<T> jit;
+ /*
+ * CDI is able to find a constructor that means that the class contains only one constructor of this type:
+ * - default constructor
+ * - non-argument constructor
+ * - multi-param constructor annotated by @Inject annotation and able to inject all parameters.
+ */
+ if (!noArgConstructor && injectionTarget instanceof BeanInjectionTarget) {
+ jit = new JerseyInjectionTarget<>(it, bean, clazz, resolvers);
+
+ /*
+ * CDI failed during the looking for a proper constructor because of these reasons:
+ * - multi-param constructor not annotated by @Inject annotation
+ * - multiple constructors annotated by @Inject annotation
+ * - is not able to satisfied single constructor annotated by @Inject annotation
+ *
+ * Therefore produced NonProducibleInjectionTarget cannot create and instance, we try to find the proper constructor
+ * using JAX-RS rules:
+ * - largest constructor with all annotated parameters
+ *
+ * If JAX-RS valid constructor is not find - InjectionException is thrown
+ */
+ } else if (noArgConstructor || injectionTarget instanceof NonProducibleInjectionTarget) {
+ CachedConstructorAnalyzer<T> analyzer =
+ new CachedConstructorAnalyzer<>(clazz, InjectionUtils.getInjectAnnotations(resolvers));
+
+ /*
+ * Contains the analyzed class any constructor that can be injected by Jersey?
+ */
+ if (analyzer.hasCompatibleConstructor()) {
+ EnhancedAnnotatedConstructor<T> constructor = createEnhancedAnnotatedType(it)
+ .getDeclaredEnhancedConstructor(new ConstructorSignatureImpl(analyzer.getConstructor()));
+
+ JerseyConstructorInjectionPoint<T> constructorInjectionPoint =
+ new JerseyConstructorInjectionPoint<>(constructor, bean, it.getBeanManager(), resolvers);
+
+ Instantiator<T> instantiator = new JerseyInstantiator<>(constructorInjectionPoint);
+ jit = new JerseyInjectionTarget<>(createEnhancedAnnotatedType(it), it, bean, clazz, resolvers, instantiator);
+
+ /*
+ * Instance of this class cannot be created neither CDI nor Jersey therefore mark it as non-producible.
+ */
+ } else {
+ return new WrappingJerseyInjectionTarget<>(it, bean, resolvers);
+ }
+ } else {
+ throw new RuntimeException("Unknown InjectionTarget for the class: " + clazz.getTypeName());
+ }
+
+ InjectionTargetService injectionTargetService = it.getBeanManager().getServices().get(InjectionTargetService.class);
+ injectionTargetService.addInjectionTargetToBeInitialized(jit.getEnhancedAnnotatedType(), jit);
+ return jit;
+ }
+
+ public static <T> EnhancedAnnotatedType<T> createEnhancedAnnotatedType(BasicInjectionTarget<T> it) {
+ return EnhancedAnnotatedTypeImpl.of(
+ (SlimAnnotatedType<T>) it.getAnnotatedType(), ClassTransformer.instance(it.getBeanManager()));
+ }
+
+ /**
+ * Looks at whether the DefaultInstantiator resolving a valid constructor does not met this case:
+ * - No constructor with @Inject annotation is defined
+ * - NoArgs constructor is defined
+ * - Instantiator ignores JAX-RS valid constructor with multiple params
+ *
+ * @param it injection target containing instantiator with resolved constructor.
+ * @param clazz class which analyzed constructor belongs to.
+ * @param <T> type of the analyzed class.
+ * @return {@code true} if no-arg constructor was selected while multi-params constructor exists.
+ */
+ private static <T> boolean isNoArgConstructorCase(BasicInjectionTarget<T> it, Class<T> clazz) {
+ if (!(it instanceof NonProducibleInjectionTarget)) {
+ Instantiator<T> instantiator = it.getInstantiator();
+ Constructor<T> constructor = instantiator.getConstructor();
+ return constructor.getParameterCount() == 0 && clazz.getConstructors().length > 1;
+ }
+
+ return false;
+ }
+
+ /**
+ * Wrapper class to provide Jersey implementation of {@link Instantiator} interface.
+ *
+ * @param <T> type which is created by instantiator.
+ */
+ private static class JerseyInstantiator<T> extends AbstractInstantiator<T> {
+
+ private final ConstructorInjectionPoint<T> injectionPoint;
+
+ private JerseyInstantiator(ConstructorInjectionPoint<T> injectionPoint) {
+ this.injectionPoint = injectionPoint;
+ }
+
+ @Override
+ public ConstructorInjectionPoint<T> getConstructorInjectionPoint() {
+ return injectionPoint;
+ }
+
+ @Override
+ public Constructor<T> getConstructor() {
+ return injectionPoint.getAnnotated().getJavaMember();
+ }
+
+ @Override
+ public String toString() {
+ return "JerseyInstantiator [constructor=" + injectionPoint.getMember() + "]";
+ }
+
+ @Override
+ public boolean hasInterceptorSupport() {
+ return false;
+ }
+
+ @Override
+ public boolean hasDecoratorSupport() {
+ return false;
+ }
+ }
+
+ public static boolean isResourceClass(Class<?> clazz) {
+ if (isJaxrsResource(clazz)) {
+ return true;
+ }
+
+ for (Class<?> iface : clazz.getInterfaces()) {
+ if (isJaxrsResource(iface)) {
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ private static boolean isJaxrsResource(Class<?> clazz) {
+ if (clazz.isAnnotationPresent(Path.class)) {
+ return true;
+ }
+
+ for (Method method : clazz.getMethods()) {
+ if (method.isAnnotationPresent(Path.class)) {
+ return true;
+ }
+
+ for (Annotation annotation : method.getAnnotations()) {
+ if (annotation.annotationType().isAnnotationPresent(HttpMethod.class)) {
+ return true;
+ }
+ }
+ }
+
+ return false;
+ }
+}
diff --git a/incubator/cdi-inject-weld/src/main/java/org/glassfish/jersey/inject/weld/internal/bean/ClassBean.java b/incubator/cdi-inject-weld/src/main/java/org/glassfish/jersey/inject/weld/internal/bean/ClassBean.java
new file mode 100644
index 0000000..6c3d6b8
--- /dev/null
+++ b/incubator/cdi-inject-weld/src/main/java/org/glassfish/jersey/inject/weld/internal/bean/ClassBean.java
@@ -0,0 +1,140 @@
+/*
+ * Copyright (c) 2021 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.inject.weld.internal.bean;
+
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Type;
+import java.util.Arrays;
+import java.util.Set;
+
+import javax.enterprise.context.Dependent;
+import javax.enterprise.context.RequestScoped;
+import javax.enterprise.context.spi.CreationalContext;
+import javax.enterprise.inject.spi.InjectionPoint;
+import javax.enterprise.inject.spi.InjectionTarget;
+import javax.ws.rs.RuntimeType;
+
+import org.glassfish.jersey.inject.weld.internal.injector.JerseyInjectionTarget;
+import org.glassfish.jersey.internal.inject.ClassBinding;
+
+/**
+ * Creates an implementation of {@link javax.enterprise.inject.spi.Bean} interface using Jersey's {@link ClassBinding}. Binding
+ * provides the information about the bean also called {@link javax.enterprise.inject.spi.BeanAttributes} information and
+ * {@link JerseyInjectionTarget} provides the contextual part of the bean because implements
+ * {@link javax.enterprise.context.spi.Contextual} with Jersey injection extension (is able to inject into JAX-RS/Jersey specified
+ * annotation).
+ * <p>
+ * Inject example:
+ * <pre>
+ * AbstractBinder {
+ * @Override
+ * protected void configure() {
+ * bind(MyBean.class)
+ * .to(MyBean.class)
+ * .in(Singleton.class);
+ * }
+ * }
+ * </pre>
+ * Register example:
+ * <pre>
+ * @Path("/")
+ * public class MyResource {
+ * @Inject
+ * private MyBean myBean;
+ * }
+ * </pre>
+ *
+ * @author Petr Bouda
+ */
+class ClassBean<T> extends JerseyBean<T> {
+
+ private final ClassBinding<T> binding;
+ private InjectionTarget<T> injectionTarget;
+
+ /**
+ * Creates a new Jersey-specific {@link javax.enterprise.inject.spi.Bean} instance.
+ * @param runtimeType {@link RuntimeType} type information of the bean source.
+ * @param binding the binding information.
+ */
+ ClassBean(RuntimeType runtimeType, ClassBinding<T> binding) {
+ super(runtimeType, binding);
+ this.binding = binding;
+ }
+
+ @Override
+ public Class<? extends Annotation> getScope() {
+ /*
+ * Resource class without the Scope annotation should registered as a RequestScoped.
+ */
+ if (binding.getScope() == null && BeanHelper.isResourceClass(binding.getService())) {
+ return RequestScoped.class;
+ }
+
+ return binding.getScope() == null ? Dependent.class : transformScope(binding.getScope());
+ }
+
+ @Override
+ @SuppressWarnings("unchecked")
+ public T create(CreationalContext<T> context) {
+ T instance = injectionTarget.produce(context);
+ injectionTarget.inject(instance, context);
+ injectionTarget.postConstruct(instance);
+ return instance;
+ }
+
+ @Override
+ public void destroy(T instance, CreationalContext<T> context) {
+ injectionTarget.preDestroy(instance);
+ injectionTarget.dispose(instance);
+ context.release();
+ }
+
+ @Override
+ public Set<Type> getTypes() {
+ Set<Type> contracts = super.getTypes();
+ contracts.addAll(Arrays.asList(binding.getService().getInterfaces()));
+ return contracts;
+ }
+
+ @Override
+ public Class<?> getBeanClass() {
+ return binding.getService();
+ }
+
+ @Override
+ public Set<InjectionPoint> getInjectionPoints() {
+ return injectionTarget.getInjectionPoints();
+ }
+
+ /**
+ * Lazy set of an injection target because to create fully functional injection target needs already created bean.
+ *
+ * @param injectionTarget {@link javax.enterprise.context.spi.Contextual} information belonging to this bean.
+ */
+ void setInjectionTarget(InjectionTarget<T> injectionTarget) {
+ this.injectionTarget = injectionTarget;
+ }
+
+ @Override
+ public String toString() {
+ return "ClassBean{" + getBeanClass() + "(" + getRutimeType() + ")}";
+ }
+
+ public InjectionTarget<T> getInjectionTarget() {
+ return injectionTarget;
+ }
+}
diff --git a/incubator/cdi-inject-weld/src/main/java/org/glassfish/jersey/inject/weld/internal/bean/InitializableInstanceBean.java b/incubator/cdi-inject-weld/src/main/java/org/glassfish/jersey/inject/weld/internal/bean/InitializableInstanceBean.java
new file mode 100644
index 0000000..f319a4f
--- /dev/null
+++ b/incubator/cdi-inject-weld/src/main/java/org/glassfish/jersey/inject/weld/internal/bean/InitializableInstanceBean.java
@@ -0,0 +1,80 @@
+/*
+ * Copyright (c) 2021 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+package org.glassfish.jersey.inject.weld.internal.bean;
+
+import javax.enterprise.context.Dependent;
+import javax.enterprise.context.spi.CreationalContext;
+import javax.enterprise.inject.spi.InjectionTarget;
+import javax.ws.rs.RuntimeType;
+
+import org.glassfish.jersey.inject.weld.internal.inject.InitializableInstanceBinding;
+import org.glassfish.jersey.inject.weld.internal.injector.JerseyClientCreationalContext;
+
+import java.lang.annotation.Annotation;
+
+/**
+ * Instance bean to be created in the pre-initialization phase and initialized after Jersey is bootstrap.
+ * @param <T> the class of the bean instance.
+ */
+public class InitializableInstanceBean<T> extends JerseyBean<T> {
+
+ private InjectionTarget<T> injectionTarget;
+
+ /**
+ * Creates a new Jersey-specific {@link javax.enterprise.inject.spi.Bean} instance.
+ *
+ * @param binding {@link javax.enterprise.inject.spi.BeanAttributes} part of the bean.
+ */
+ InitializableInstanceBean(RuntimeType runtimeType, InitializableInstanceBinding<T> binding) {
+ super(runtimeType, binding);
+ }
+
+ @Override
+ public Class<? extends Annotation> getScope() {
+ return getBinding().getScope() == null ? Dependent.class : transformScope(getBinding().getScope());
+ }
+
+ @Override
+ public T create(CreationalContext<T> context) {
+ InitializableInstanceBinding<T> realBinding = (InitializableInstanceBinding<T>) getBinding();
+ if (JerseyClientCreationalContext.class.isInstance(context)) {
+ realBinding = ((JerseyClientCreationalContext) context).getInjectionManager().getInjectionManagerBinding(realBinding);
+ }
+ T service = realBinding.getService();
+ this.injectionTarget.inject(service, context);
+ return service;
+ }
+
+ @Override
+ public Class<?> getBeanClass() {
+ final InitializableInstanceBinding<T> binding = (InitializableInstanceBinding<T>) getBinding();
+ return binding.isInit() ? binding.getImplementationType() : Object.class;
+ }
+
+ /**
+ * Lazy set of an injection target because to create fully functional injection target needs already created bean.
+ *
+ * @param injectionTarget {@link javax.enterprise.context.spi.Contextual} information belonging to this bean.
+ */
+ void setInjectionTarget(InjectionTarget<T> injectionTarget) {
+ this.injectionTarget = injectionTarget;
+ }
+
+ @Override
+ public String toString() {
+ return "InitializableInstanceBean{" + getBeanClass() + "}";
+ }
+}
diff --git a/incubator/cdi-inject-weld/src/main/java/org/glassfish/jersey/inject/weld/internal/bean/InitializableSupplierInstanceBean.java b/incubator/cdi-inject-weld/src/main/java/org/glassfish/jersey/inject/weld/internal/bean/InitializableSupplierInstanceBean.java
new file mode 100644
index 0000000..cbaaf0c
--- /dev/null
+++ b/incubator/cdi-inject-weld/src/main/java/org/glassfish/jersey/inject/weld/internal/bean/InitializableSupplierInstanceBean.java
@@ -0,0 +1,118 @@
+/*
+ * Copyright (c) 2021 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.inject.weld.internal.bean;
+
+import javax.enterprise.context.Dependent;
+import javax.enterprise.context.spi.CreationalContext;
+import javax.ws.rs.RuntimeType;
+
+import org.glassfish.jersey.inject.weld.internal.inject.InitializableSupplierInstanceBinding;
+import org.glassfish.jersey.inject.weld.internal.injector.JerseyClientCreationalContext;
+import org.glassfish.jersey.inject.weld.internal.injector.JerseyInjectionTarget;
+import org.glassfish.jersey.inject.weld.internal.type.ParameterizedTypeImpl;
+import org.glassfish.jersey.internal.inject.DisposableSupplier;
+import org.glassfish.jersey.internal.inject.SupplierInstanceBinding;
+
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Type;
+import java.util.HashSet;
+import java.util.Set;
+import java.util.function.Supplier;
+
+/**
+ * Creates an implementation of {@link javax.enterprise.inject.spi.Bean} interface using Jersey's {@link SupplierInstanceBinding}.
+ * Binding provides the information about the bean also called {@link javax.enterprise.inject.spi.BeanAttributes} information.
+ * The {@code Bean} does not use {@link JerseyInjectionTarget} because serves already
+ * created supplier instance, therefore the create operation just return provided instance without any other contextual operation
+ * (produce, inject, destroy). Client has to manage the instance alone.
+ * <p>
+ * Inject example:
+ * <pre>
+ * AbstractBinder {
+ * @Override
+ * protected void configure() {
+ * bindFactory(new MyBeanFactory())
+ * .to(MyBean.class)
+ * .in(Singleton.class);
+ * }
+ * }
+ * </pre>
+ * Register example:
+ * <pre>
+ * @Path("/")
+ * public class MyResource {
+ * @Inject
+ * private Supplier<MyBean> myBean;
+ * }
+ * </pre>
+ *
+ * @author Petr Bouda
+ */
+class InitializableSupplierInstanceBean<T> extends JerseyBean<Supplier<T>> {
+
+ private final Set<Type> contracts = new HashSet<>();
+ private final Supplier<T> supplier;
+
+ /**
+ * Creates a new Jersey-specific {@link javax.enterprise.inject.spi.Bean} instance.
+ *
+ * @param binding {@link javax.enterprise.inject.spi.BeanAttributes} part of the bean.
+ */
+ InitializableSupplierInstanceBean(RuntimeType runtimeType, InitializableSupplierInstanceBinding<T> binding) {
+ super(runtimeType, binding);
+ this.supplier = binding.getSupplier();
+
+ for (Type contract: binding.getContracts()) {
+ this.contracts.add(new ParameterizedTypeImpl(Supplier.class, contract));
+ if (DisposableSupplier.class.isAssignableFrom(binding.getSupplier().getClass())) {
+ this.contracts.add(new ParameterizedTypeImpl(DisposableSupplier.class, contract));
+ }
+ }
+ }
+
+ @Override
+ public Set<Type> getTypes() {
+ return contracts;
+ }
+
+ @Override
+ public Set<Annotation> getQualifiers() {
+ return DEFAULT_QUALIFIERS;
+ }
+
+ @Override
+ public Supplier<T> create(CreationalContext<Supplier<T>> context) {
+ if (JerseyClientCreationalContext.class.isInstance(context)) {
+ final InitializableSupplierInstanceBinding<T> binding = (InitializableSupplierInstanceBinding<T>) getBinding();
+ final JerseyClientCreationalContext jerseyContext = (JerseyClientCreationalContext) context;
+ return jerseyContext.getInjectionManager().getInjectionManagerBinding(binding).getSupplier();
+ } else {
+ return supplier;
+ }
+ }
+
+ @Override
+ public Class<?> getBeanClass() {
+ final InitializableSupplierInstanceBinding binding = (InitializableSupplierInstanceBinding) getBinding();
+ return binding.isInit() ? binding.getOriginalSupplier().getClass() : Object.class;
+ }
+
+ @Override
+ public Class<? extends Annotation> getScope() {
+ return getBinding().getScope() == null ? Dependent.class : transformScope(getBinding().getScope());
+ }
+}
diff --git a/incubator/cdi-inject-weld/src/main/java/org/glassfish/jersey/inject/weld/internal/bean/InitializableSupplierInstanceBeanBridge.java b/incubator/cdi-inject-weld/src/main/java/org/glassfish/jersey/inject/weld/internal/bean/InitializableSupplierInstanceBeanBridge.java
new file mode 100644
index 0000000..c86d44f
--- /dev/null
+++ b/incubator/cdi-inject-weld/src/main/java/org/glassfish/jersey/inject/weld/internal/bean/InitializableSupplierInstanceBeanBridge.java
@@ -0,0 +1,105 @@
+/*
+ * Copyright (c) 2021 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.inject.weld.internal.bean;
+
+import javax.enterprise.context.Dependent;
+import javax.enterprise.context.spi.CreationalContext;
+import javax.ws.rs.RuntimeType;
+
+import org.glassfish.jersey.inject.weld.internal.inject.InitializableSupplierInstanceBinding;
+import org.glassfish.jersey.inject.weld.internal.injector.JerseyInjectionTarget;
+import org.glassfish.jersey.internal.inject.DisposableSupplier;
+import org.glassfish.jersey.internal.inject.SupplierInstanceBinding;
+
+import java.lang.annotation.Annotation;
+import java.util.function.Supplier;
+
+/**
+ * Creates an implementation of {@link javax.enterprise.inject.spi.Bean} interface using Jersey's {@link SupplierInstanceBinding}.
+ * Binding provides the information about the bean also called {@link javax.enterprise.inject.spi.BeanAttributes} information.
+ * The {@code Bean} does not use {@link JerseyInjectionTarget} because serves already
+ * created instances, therefore the create operation just return provided instance without any other contextual operation
+ * (produce, inject, destroy). Client has to manage the instance alone.
+ * <p>
+ * This implementation works as bridge between {@link Supplier} and its provided value. This solves the case when the concrete
+ * type of supplier value is fetched from {@link org.glassfish.jersey.internal.inject.InjectionManager} then this
+ * {@link javax.enterprise.inject.spi.Bean} implementation just invokes {@link Supplier#get} method on underlying/registered
+ * supplier.
+ * <p>
+ * Inject example:
+ * <pre>
+ * AbstractBinder {
+ * @Override
+ * protected void configure() {
+ * bindFactory(new MyBeanFactory())
+ * .to(MyBean.class)
+ * .in(Singleton.class);
+ * }
+ * }
+ * </pre>
+ * Register example:
+ * <pre>
+ * @Path("/")
+ * public class MyResource {
+ * @Inject
+ * private MyBean myBean;
+ * }
+ * </pre>
+ *
+ * @author Petr Bouda
+ */
+class InitializableSupplierInstanceBeanBridge<T> extends JerseyBean<Object> {
+
+ private final Supplier<T> supplier;
+ private final Class<? extends Annotation> scope;
+
+ /**
+ * Creates a new Jersey-specific {@link javax.enterprise.inject.spi.Bean} instance.
+ *
+ * @param binding {@link javax.enterprise.inject.spi.BeanAttributes} part of the bean.
+ */
+ @SuppressWarnings("unchecked")
+ InitializableSupplierInstanceBeanBridge(RuntimeType runtimeType, InitializableSupplierInstanceBinding binding) {
+ super(runtimeType, binding);
+
+ InitializableSupplierInstanceBinding<T> casted = (InitializableSupplierInstanceBinding<T>) binding;
+ this.supplier = casted.getSupplier();
+ this.scope = casted.getScope();
+ }
+
+ @Override
+ public Object create(CreationalContext creationalContext) {
+ return supplier.get();
+ }
+
+ @Override
+ public void destroy(Object instance, CreationalContext<Object> context) {
+ if (DisposableSupplier.class.isAssignableFrom(supplier.getClass())) {
+ ((DisposableSupplier<Object>) supplier).dispose(instance);
+ }
+ }
+
+ /**
+ * {@link InitializableSupplierInstanceBeanBridge} needs have the same scope as a keeping value.
+ *
+ * @return scope of the supplier bean.
+ */
+ @Override
+ public Class<? extends Annotation> getScope() {
+ return scope == null ? Dependent.class : transformScope(scope);
+ }
+}
diff --git a/incubator/cdi-inject-weld/src/main/java/org/glassfish/jersey/inject/weld/internal/bean/InitializableSupplierThreadScopeBean.java b/incubator/cdi-inject-weld/src/main/java/org/glassfish/jersey/inject/weld/internal/bean/InitializableSupplierThreadScopeBean.java
new file mode 100644
index 0000000..5f144e0
--- /dev/null
+++ b/incubator/cdi-inject-weld/src/main/java/org/glassfish/jersey/inject/weld/internal/bean/InitializableSupplierThreadScopeBean.java
@@ -0,0 +1,141 @@
+/*
+ * Copyright (c) 2021 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.inject.weld.internal.bean;
+
+import javax.enterprise.context.Dependent;
+import javax.enterprise.context.spi.CreationalContext;
+import javax.enterprise.inject.spi.Bean;
+import javax.enterprise.inject.spi.PassivationCapable;
+import javax.ws.rs.RuntimeType;
+
+import org.glassfish.jersey.inject.weld.internal.inject.InitializableSupplierInstanceBinding;
+import org.glassfish.jersey.inject.weld.internal.injector.JerseyInjectionTarget;
+import org.glassfish.jersey.internal.inject.SupplierInstanceBinding;
+import org.jboss.weld.bean.StringBeanIdentifier;
+import org.jboss.weld.bean.proxy.BeanInstance;
+import org.jboss.weld.bean.proxy.ContextBeanInstance;
+import org.jboss.weld.bean.proxy.ProxyFactory;
+import org.jboss.weld.manager.BeanManagerImpl;
+
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Method;
+import java.util.WeakHashMap;
+import java.util.function.Supplier;
+
+/**
+ * Creates an implementation of {@link Bean} interface using Jersey's {@link SupplierInstanceBinding}.
+ * Binding provides the information about the bean also called {@link javax.enterprise.inject.spi.BeanAttributes} information.
+ * The {@code Bean} does not use {@link JerseyInjectionTarget} because serves already
+ * created proxy, therefore the create operation just return provided instance without any other contextual operation
+ * (produce, inject, destroy).
+ * <p>
+ * This bean is special and is used only for service registered as a {@link org.glassfish.jersey.internal.inject.PerThread} and
+ * works through the proxy which serves the correct instance per the given thread.
+ * <p>
+ * Register example:
+ * <pre>
+ * AbstractBinder {
+ * @Override
+ * protected void configure() {
+ * bindFactory(new MyFactoryInjectionProvider())
+ * .to(MyBean.class)
+ * .in(PerThread.class);
+ * }
+ * }
+ * </pre>
+ * Inject example:
+ * <pre>
+ * @Path("/")
+ * public class MyResource {
+ * @Inject
+ * private MyBean myBean;
+ * }
+ * </pre>
+ */
+public class InitializableSupplierThreadScopeBean extends JerseyBean<Object> {
+
+ private final ThreadScopeBeanInstance<Object> beanInstance;
+ private final InitializableSupplierInstanceBinding binding;
+ private final Object proxy;
+
+ /**
+ * Creates a new Jersey-specific {@link Bean} instance.
+ *
+ * @param binding {@link javax.enterprise.inject.spi.BeanAttributes} part of the bean.
+ */
+ @SuppressWarnings("unchecked")
+ InitializableSupplierThreadScopeBean(RuntimeType runtimeType,
+ InitializableSupplierInstanceBinding binding,
+ BeanManagerImpl manager) {
+ super(runtimeType, binding);
+ this.binding = binding;
+ this.beanInstance = new ThreadScopeBeanInstance<>(binding.getSupplier(), this, manager.getContextId());
+ this.proxy = createClientProxy(beanInstance, manager.getContextId());
+ }
+
+ @Override
+ public Class<? extends Annotation> getScope() {
+ return Dependent.class;
+ }
+
+ @Override
+ public Object create(CreationalContext<Object> ctx) {
+ return proxy;
+ }
+
+ @Override
+ public void destroy(Object instance, CreationalContext<Object> creationalContext) {
+ this.beanInstance.dispose();
+ }
+
+ @Override
+ public Class<?> getBeanClass() {
+ return (Class<?>) this.binding.getContracts().iterator().next();
+ }
+
+ private <T> T createClientProxy(BeanInstance beanInstance, String contextId) {
+ ProxyFactory<T> factory = new ProxyFactory<>(contextId, getBeanClass(), getTypes(), this);
+ return factory.create(beanInstance);
+ }
+
+ private static class ThreadScopeBeanInstance<T> extends ContextBeanInstance<T> {
+
+ private final WeakHashMap<Thread, Object> instances = new WeakHashMap<>();
+
+ private final Supplier<T> supplier;
+
+ /**
+ * Creates a new invocation handler with supplier which provides a current injected value in proper scope.
+ *
+ * @param supplier provider of the value.
+ */
+ private ThreadScopeBeanInstance(Supplier<T> supplier, Bean<T> bean, String contextId) {
+ super(bean, new StringBeanIdentifier(((PassivationCapable) bean).getId()), contextId);
+ this.supplier = supplier;
+ }
+
+ @Override
+ public Object invoke(Object obj, Method method, Object... arguments) throws Throwable {
+ Object instance = instances.computeIfAbsent(Thread.currentThread(), thread -> supplier.get());
+ return super.invoke(instance, method, arguments);
+ }
+
+ public void dispose() {
+ this.instances.clear();
+ }
+ }
+}
diff --git a/incubator/cdi-inject-weld/src/main/java/org/glassfish/jersey/inject/weld/internal/bean/JerseyBean.java b/incubator/cdi-inject-weld/src/main/java/org/glassfish/jersey/inject/weld/internal/bean/JerseyBean.java
new file mode 100644
index 0000000..99cee8b
--- /dev/null
+++ b/incubator/cdi-inject-weld/src/main/java/org/glassfish/jersey/inject/weld/internal/bean/JerseyBean.java
@@ -0,0 +1,194 @@
+/*
+ * Copyright (c) 2021 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.inject.weld.internal.bean;
+
+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.annotation.Priority;
+import javax.enterprise.context.Dependent;
+import javax.enterprise.context.RequestScoped;
+import javax.enterprise.context.spi.CreationalContext;
+import javax.enterprise.inject.Any;
+import javax.enterprise.inject.Default;
+import javax.enterprise.inject.spi.Bean;
+import javax.enterprise.inject.spi.InjectionPoint;
+import javax.enterprise.inject.spi.PassivationCapable;
+import javax.enterprise.util.AnnotationLiteral;
+import javax.inject.Singleton;
+import javax.ws.rs.RuntimeType;
+
+import org.glassfish.jersey.internal.inject.Binding;
+import org.glassfish.jersey.internal.inject.PerLookup;
+import org.glassfish.jersey.internal.inject.PerThread;
+
+import org.jboss.weld.environment.se.contexts.ThreadScoped;
+
+/**
+ * Jersey-specific abstract class which implements {@link Bean} interface. Class particularly contains default implementations
+ * of {@link Bean} interface.
+ *
+ * @author Petr Bouda
+ */
+public abstract class JerseyBean<T> implements Bean<T>, PassivationCapable {
+
+ static final Set<Annotation> DEFAULT_QUALIFIERS;
+
+ static {
+ DEFAULT_QUALIFIERS = new HashSet<>();
+ DEFAULT_QUALIFIERS.add(new AnnotationLiteral<Default>() {});
+ DEFAULT_QUALIFIERS.add(new AnnotationLiteral<Any>() {});
+ }
+
+ public Binding<T, ?> getBinding() {
+ return binding;
+ }
+
+ private final Binding<T, ?> binding;
+ private final RuntimeType runtimeType;
+
+ /**
+ * JerseyBean constructor with {@link Binding} which represents {@link javax.enterprise.context.spi.Contextual} part of the
+ * bean.
+ *
+ * @param runtimeType
+ * @param binding information about the bean.
+ */
+ JerseyBean(RuntimeType runtimeType, Binding<T, ?> binding) {
+ this.binding = binding;
+ this.runtimeType = runtimeType == null ? RuntimeType.SERVER : runtimeType;
+ }
+
+ /**
+ * Transforms Jersey scopes/annotations to HK2 equivalents.
+ *
+ * @param scope Jersey scope/annotation.
+ * @return HK2 equivalent scope/annotation.
+ */
+ protected static Class<? extends Annotation> transformScope(Class<? extends Annotation> scope) {
+ if (scope == PerLookup.class) {
+ return Dependent.class;
+ } else if (scope == PerThread.class) {
+ return ThreadScoped.class;
+ } else if (scope == org.glassfish.jersey.process.internal.RequestScoped.class) {
+ return RequestScoped.class;
+ }
+ return scope;
+ }
+
+ @Override
+ public Set<Type> getTypes() {
+ Set<Type> contracts = new HashSet<>();
+ contracts.addAll(binding.getContracts());
+
+ // Merge aliases with the main bean
+ if (!binding.getAliases().isEmpty()) {
+ binding.getAliases().forEach(alias -> contracts.add(alias.getContract()));
+ }
+ contracts.add(Object.class);
+ return contracts;
+ }
+
+ @Override
+ public Set<Annotation> getQualifiers() {
+ Set<Annotation> qualifiers = new HashSet<>();
+ qualifiers.addAll(DEFAULT_QUALIFIERS);
+ if (binding.getQualifiers() != null) {
+ qualifiers.addAll(binding.getQualifiers());
+ }
+
+ // Merge aliases with the main bean
+ if (!binding.getAliases().isEmpty()) {
+ binding.getAliases().forEach(alias -> qualifiers.addAll(alias.getQualifiers()));
+ }
+ return qualifiers;
+ }
+
+ @Override
+ public String getName() {
+ return binding.getName();
+ }
+
+ @Override
+ public Class<? extends Annotation> getScope() {
+ return Singleton.class;
+ }
+
+ @Override
+ public Set<Class<? extends Annotation>> getStereotypes() {
+ return Collections.emptySet();
+ }
+
+ @Override
+ public boolean isAlternative() {
+ return false;
+ }
+
+ @Override
+ public boolean isNullable() {
+ return false;
+ }
+
+ @Override
+ public void destroy(T instance, CreationalContext<T> creationalContext) {
+ }
+
+ @Override
+ public Set<InjectionPoint> getInjectionPoints() {
+ return Collections.emptySet();
+ }
+
+ public int getRank() {
+ if (binding.getRank() != null) {
+ return binding.getRank();
+ }
+
+ Class<T> type = binding.getImplementationType();
+ if (type != null) {
+ Priority priority = type.getAnnotation(Priority.class);
+ if (priority != null) {
+ return priority.value();
+ }
+ }
+
+ return 1;
+ }
+
+ @Override
+ public Class<?> getBeanClass() {
+ return Object.class;
+ }
+
+ @Override
+ public String getId() {
+ // Object for Lambda
+ return (getBeanClass().equals(Object.class) ? getContractsAsString() : getBeanClass().getTypeName())
+ + "#jersey" + runtimeType;
+ }
+
+ public RuntimeType getRutimeType() {
+ return runtimeType;
+ }
+
+ public String getContractsAsString() {
+ return Arrays.toString(binding.getContracts().toArray());
+ }
+}
diff --git a/incubator/cdi-inject-weld/src/main/java/org/glassfish/jersey/inject/weld/internal/bean/SupplierBeanBridge.java b/incubator/cdi-inject-weld/src/main/java/org/glassfish/jersey/inject/weld/internal/bean/SupplierBeanBridge.java
new file mode 100644
index 0000000..0a3c247
--- /dev/null
+++ b/incubator/cdi-inject-weld/src/main/java/org/glassfish/jersey/inject/weld/internal/bean/SupplierBeanBridge.java
@@ -0,0 +1,160 @@
+/*
+ * Copyright (c) 2021 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.inject.weld.internal.bean;
+
+import java.lang.annotation.Annotation;
+import java.lang.reflect.ParameterizedType;
+import java.lang.reflect.Type;
+import java.util.IdentityHashMap;
+import java.util.Map;
+import java.util.Set;
+import java.util.function.Supplier;
+
+import javax.enterprise.context.Dependent;
+import javax.enterprise.context.spi.CreationalContext;
+import javax.enterprise.inject.spi.Bean;
+import javax.enterprise.inject.spi.BeanManager;
+import javax.ws.rs.RuntimeType;
+
+import org.glassfish.jersey.inject.weld.internal.injector.JerseyInjectionTarget;
+import org.glassfish.jersey.inject.weld.managed.CdiInjectionManagerFactory;
+import org.glassfish.jersey.inject.weld.internal.type.ParameterizedTypeImpl;
+import org.glassfish.jersey.internal.inject.DisposableSupplier;
+import org.glassfish.jersey.internal.inject.InjectionManager;
+import org.glassfish.jersey.internal.inject.SupplierClassBinding;
+import org.glassfish.jersey.internal.inject.SupplierInstanceBinding;
+
+/**
+ * Creates an implementation of {@link javax.enterprise.inject.spi.Bean} interface using Jersey's {@link SupplierInstanceBinding}.
+ * Binding provides the information about the bean also called {@link javax.enterprise.inject.spi.BeanAttributes} information.
+ * The {@code Bean} does not use {@link JerseyInjectionTarget} because serves already
+ * the instances created by underlying {@link Supplier} injected target on which the call is delegated.
+ * <p>
+ * This implementation works as bridge between {@link Supplier} and its provided value. This solves the case when the concrete
+ * type of supplier value is fetched from {@link org.glassfish.jersey.internal.inject.InjectionManager} then this
+ * {@link javax.enterprise.inject.spi.Bean} implementation just invokes {@link Supplier#get} method on underlying/registered
+ * supplier.
+ * <p>
+ * Inject example:
+ * <pre>
+ * AbstractBinder {
+ * @Override
+ * protected void configure() {
+ * bindFactory(MyBeanFactory.class)
+ * .to(MyBean.class)
+ * .in(Singleton.class);
+ * }
+ * }
+ * </pre>
+ * Register example:
+ * <pre>
+ * @Path("/")
+ * public class MyResource {
+ * @Inject
+ * private MyBean myBean;
+ * }
+ * </pre>
+ *
+ * @author Petr Bouda
+ */
+class SupplierBeanBridge extends JerseyBean<Object> {
+
+ private final BeanManager beanManager;
+ private ParameterizedType type;
+ private boolean disposable;
+ private SupplierClassBinding binding;
+
+ // This bridge can create multiple instances using the method 'provide' therefore must map created suppliers because of
+ // 'dispose' invocation later on.
+ // TODO: Key as a WeakReference - prevent objects in scope which never dispose the objects such as PerLookup.
+ private final Map<Object, DisposableSupplier<Object>> disposableSuppliers = new IdentityHashMap<>();
+
+ /**
+ * Creates a new Jersey-specific {@link javax.enterprise.inject.spi.Bean} instance.
+ *
+ * @param binding {@link javax.enterprise.inject.spi.BeanAttributes} part of the bean.
+ */
+ @SuppressWarnings("unchecked")
+ SupplierBeanBridge(RuntimeType runtimeType, SupplierClassBinding binding, BeanManager beanManager) {
+ super(runtimeType, binding);
+
+ // Register wrapper for factory functionality, wrapper automatically call service locator which is able to retrieve
+ // the service in the proper context and scope. Bridge is registered for all contracts but is able to lookup from
+ // service locator only using the first contract.
+ Type contract = null;
+ if (binding.getContracts().iterator().hasNext()) {
+ contract = (Type) binding.getContracts().iterator().next();
+ }
+
+ this.binding = binding;
+ this.beanManager = beanManager;
+ this.disposable = DisposableSupplier.class.isAssignableFrom(binding.getSupplierClass());
+ this.type = new ParameterizedTypeImpl(Supplier.class, contract);
+ }
+
+ @Override
+ @SuppressWarnings("unchecked")
+ public Object create(CreationalContext creationalContext) {
+ if (type != null) {
+ InjectionManager injectionManager = CdiInjectionManagerFactory.getInjectionManager(creationalContext);
+ Supplier<?> supplier = injectionManager.getInstance(type);
+
+ //Supplier<?> supplier = getSupplier(beanManager, type);
+ Object instance = supplier.get();
+ if (disposable) {
+ disposableSuppliers.put(instance, (DisposableSupplier) supplier);
+ }
+ return instance;
+ } else {
+ return null;
+ }
+ }
+
+ @Override
+ @SuppressWarnings("unchecked")
+ public void destroy(Object instance, CreationalContext context) {
+ if (disposable) {
+ DisposableSupplier disposableSupplier = disposableSuppliers.get(instance);
+ disposableSupplier.dispose(instance);
+ disposableSuppliers.remove(instance);
+ }
+ }
+
+ private static Supplier<?> getSupplier(BeanManager beanManager, ParameterizedType supplierType) {
+ Set<Bean<?>> beans = beanManager.getBeans(supplierType);
+ if (beans.isEmpty()) {
+ return null;
+ }
+
+ Bean<?> bean = beans.iterator().next();
+ CreationalContext<?> ctx = beanManager.createCreationalContext(bean);
+ return (Supplier<?>) beanManager.getReference(bean, supplierType, ctx);
+ }
+
+ @Override
+ @SuppressWarnings("unchecked")
+ public Class<? extends Annotation> getScope() {
+ return binding.getScope() == null ? Dependent.class : transformScope(binding.getScope());
+ }
+
+ @Override
+ public Class<?> getBeanClass() {
+ return this.binding.getContracts().isEmpty()
+ ? super.getBeanClass()
+ : (Class<?>) this.binding.getContracts().iterator().next();
+ }
+}
diff --git a/incubator/cdi-inject-weld/src/main/java/org/glassfish/jersey/inject/weld/internal/bean/SupplierClassBean.java b/incubator/cdi-inject-weld/src/main/java/org/glassfish/jersey/inject/weld/internal/bean/SupplierClassBean.java
new file mode 100644
index 0000000..5ae244d
--- /dev/null
+++ b/incubator/cdi-inject-weld/src/main/java/org/glassfish/jersey/inject/weld/internal/bean/SupplierClassBean.java
@@ -0,0 +1,133 @@
+/*
+ * Copyright (c) 2021 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.inject.weld.internal.bean;
+
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Type;
+import java.util.HashSet;
+import java.util.Set;
+import java.util.function.Supplier;
+
+import javax.enterprise.context.Dependent;
+import javax.enterprise.context.spi.CreationalContext;
+import javax.enterprise.inject.spi.InjectionTarget;
+import javax.ws.rs.RuntimeType;
+
+import org.glassfish.jersey.inject.weld.internal.injector.JerseyInjectionTarget;
+import org.glassfish.jersey.inject.weld.internal.type.ParameterizedTypeImpl;
+import org.glassfish.jersey.internal.inject.DisposableSupplier;
+import org.glassfish.jersey.internal.inject.SupplierClassBinding;
+
+/**
+ * Creates an implementation of {@link javax.enterprise.inject.spi.Bean} interface using Jersey's {@link SupplierClassBinding}.
+ * Binding provides the information about the bean also called {@link javax.enterprise.inject.spi.BeanAttributes} information and
+ * {@link JerseyInjectionTarget} provides the contextual part of the bean because implements
+ * {@link javax.enterprise.context.spi.Contextual} with Jersey injection extension (is able to inject into JAX-RS/Jersey specified
+ * annotation).
+ * <p>
+ * Bean's implementation provides possibility to register {@link Supplier} and {@link DisposableSupplier}.
+ * <p>
+ * Inject example:
+ * <pre>
+ * AbstractBinder {
+ * @Override
+ * protected void configure() {
+ * bindFactory(MyBeanSupplier.class)
+ * .to(MyBean.class)
+ * .in(Singleton.class);
+ * }
+ * }
+ * </pre>
+ * Register example:
+ * <pre>
+ * @Path("/")
+ * public class MyResource {
+ * @Inject
+ * private Supplier<MyBean> myBean;
+ * }
+ * </pre>
+ *
+ * @author Petr Bouda
+ */
+class SupplierClassBean<T> extends JerseyBean<Supplier<T>> {
+
+ private final Set<Type> contracts = new HashSet<>();
+ private final Class<? extends Supplier<T>> supplierClass;
+ private final Class<? extends Annotation> supplierScope;
+ private InjectionTarget<Supplier<T>> injectionTarget;
+
+ /**
+ * Creates a new Jersey-specific {@link javax.enterprise.inject.spi.Bean} instance.
+ *
+ * @param binding {@link javax.enterprise.inject.spi.BeanAttributes} part of the bean.
+ */
+ SupplierClassBean(RuntimeType runtimeType, SupplierClassBinding<T> binding) {
+ super(runtimeType, binding);
+ this.supplierClass = binding.getSupplierClass();
+ this.supplierScope = binding.getSupplierScope();
+
+ for (Type contract : binding.getContracts()) {
+ this.contracts.add(new ParameterizedTypeImpl(Supplier.class, contract));
+ if (DisposableSupplier.class.isAssignableFrom(supplierClass)) {
+ this.contracts.add(new ParameterizedTypeImpl(DisposableSupplier.class, contract));
+ }
+ }
+ }
+
+ @Override
+ public Class<? extends Annotation> getScope() {
+ return supplierScope == null ? Dependent.class : transformScope(supplierScope);
+ }
+
+ @Override
+ public Set<Type> getTypes() {
+ return contracts;
+ }
+
+ @Override
+ public Supplier<T> create(CreationalContext<Supplier<T>> context) {
+ Supplier<T> instance = injectionTarget.produce(context);
+ injectionTarget.inject(instance, context);
+ injectionTarget.postConstruct(instance);
+ return instance;
+ }
+
+ @Override
+ public void destroy(Supplier<T> instance, CreationalContext<Supplier<T>> context) {
+ injectionTarget.preDestroy(instance);
+ injectionTarget.dispose(instance);
+ context.release();
+ }
+
+ @Override
+ public Class<?> getBeanClass() {
+ return supplierClass;
+ }
+
+ /**
+ * Lazy set of an injection target because to create fully functional injection target needs already created bean.
+ *
+ * @param injectionTarget {@link javax.enterprise.context.spi.Contextual} information belonging to this bean.
+ */
+ void setInjectionTarget(InjectionTarget<Supplier<T>> injectionTarget) {
+ this.injectionTarget = injectionTarget;
+ }
+
+ public InjectionTarget<Supplier<T>> getInjectionTarget() {
+ return injectionTarget;
+ }
+}
diff --git a/incubator/cdi-inject-weld/src/main/java/org/glassfish/jersey/inject/weld/internal/data/BindingBeanPair.java b/incubator/cdi-inject-weld/src/main/java/org/glassfish/jersey/inject/weld/internal/data/BindingBeanPair.java
new file mode 100644
index 0000000..1d0b2c9
--- /dev/null
+++ b/incubator/cdi-inject-weld/src/main/java/org/glassfish/jersey/inject/weld/internal/data/BindingBeanPair.java
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2021 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+package org.glassfish.jersey.inject.weld.internal.data;
+
+import org.glassfish.jersey.inject.weld.internal.bean.JerseyBean;
+import org.glassfish.jersey.internal.inject.Binding;
+
+import java.util.LinkedList;
+import java.util.List;
+
+/**
+ * Pair of a binding and corresponding Jersey beans.
+ */
+public class BindingBeanPair {
+ private final Binding binding;
+ private final List<JerseyBean> beans = new LinkedList<JerseyBean>();
+
+ public BindingBeanPair(Binding binding, JerseyBean... beans) {
+ this.binding = binding;
+ if (beans != null) {
+ for (JerseyBean bean : beans) {
+ this.beans.add(bean);
+ }
+ }
+ }
+
+ public Binding getBinding() {
+ return binding;
+ }
+
+ public List<JerseyBean> getBeans() {
+ return beans;
+ }
+}
diff --git a/incubator/cdi-inject-weld/src/main/java/org/glassfish/jersey/inject/weld/internal/inject/InitializableInstanceBinding.java b/incubator/cdi-inject-weld/src/main/java/org/glassfish/jersey/inject/weld/internal/inject/InitializableInstanceBinding.java
new file mode 100644
index 0000000..61b4a2c
--- /dev/null
+++ b/incubator/cdi-inject-weld/src/main/java/org/glassfish/jersey/inject/weld/internal/inject/InitializableInstanceBinding.java
@@ -0,0 +1,186 @@
+/*
+ * Copyright (c) 2021 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.inject.weld.internal.inject;
+
+import org.glassfish.jersey.internal.inject.AliasBinding;
+import org.glassfish.jersey.internal.inject.Binding;
+import org.glassfish.jersey.internal.inject.Bindings;
+import org.glassfish.jersey.internal.inject.InstanceBinding;
+
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Type;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.Set;
+import java.util.concurrent.atomic.AtomicBoolean;
+
+/**
+ * Injection binding description of a bean bound directly as a specific instance to be created in a pre-initialization phase
+ * and initialized in runtime.
+ *
+ * @param <T> Type of the service described by this injection binding.
+ */
+public class InitializableInstanceBinding<T> extends MatchableBinding<T, InitializableInstanceBinding<T>> implements Cloneable {
+
+ protected T service;
+ private AtomicBoolean isInit = new AtomicBoolean(false);
+ private Class<T> implementationType;
+
+ /**
+ * Creates a service as an instance.
+ *
+ * @param service service's instance.
+ */
+ protected InitializableInstanceBinding(T service) {
+ this(service, null);
+ }
+
+ /**
+ * Creates a service as an instance.
+ *
+ * @param service service's instance.
+ * @param contractType service's contractType.
+ */
+ private InitializableInstanceBinding(T service, Type contractType) {
+ this.service = service;
+ this.implementationType = service == null ? null : (Class<T>) service.getClass();
+ if (contractType != null) {
+ this.to(contractType);
+ }
+ }
+
+ /**
+ * Gets service' class.
+ *
+ * @return service's class.
+ */
+ public T getService() {
+ if (!isInit.get()) {
+ String types = Arrays.toString(getContracts().toArray());
+ throw new IllegalStateException("Not initialized " + service + "(" + types + ")");
+ }
+ return service;
+ }
+
+ /**
+ * Gets service's type.
+ *
+ * @return service's type.
+ */
+ public Class<T> getImplementationType() {
+ return implementationType;
+ }
+
+ public void init(T service) {
+ if (!isInit.getAndSet(true)) {
+ this.service = service;
+ implementationType = (Class<T>) service.getClass();
+ } else if (this.service != service) {
+ throw new IllegalStateException("Multiple initialized for " + service.getClass());
+ }
+ }
+
+ public boolean isInit() {
+ return isInit.get();
+ }
+
+ public Matching<InitializableInstanceBinding<T>> matches(Binding other) {
+ return super.matches(other);
+ }
+
+ @Override
+ public InitializableInstanceBinding<T> clone() {
+ throw new RuntimeException(new CloneNotSupportedException());
+ }
+
+ public static <T> InitializableInstanceBinding<T> from(InstanceBinding<T> instanceBinding) {
+ return new InitializableWrappingInstanceBinding(instanceBinding);
+ }
+
+ @Override
+ protected MatchLevel bestMatchLevel() {
+ return MatchLevel.IMPLEMENTATION;
+ }
+
+ private static class InitializableWrappingInstanceBinding<T> extends InitializableInstanceBinding<T> {
+ private final InstanceBinding<T> wrapped;
+ public InitializableWrappingInstanceBinding(InstanceBinding<T> binding) {
+ super(binding.getService());
+ wrapped = binding;
+ }
+
+ private InitializableWrappingInstanceBinding(InitializableWrappingInstanceBinding<T> binding) {
+ super(binding.service);
+ wrapped = binding.wrapped;
+ }
+
+ @Override
+ public Class<T> getImplementationType() {
+ return super.getImplementationType();
+ }
+
+ @Override
+ public T getService() {
+ return super.getService();
+ }
+
+ @Override
+ public Class<? extends Annotation> getScope() {
+ return wrapped.getScope();
+ }
+
+ @Override
+ public Set<Type> getContracts() {
+ return wrapped.getContracts();
+ }
+
+ @Override
+ public Integer getRank() {
+ return wrapped.getRank();
+ }
+
+ @Override
+ public Set<AliasBinding> getAliases() {
+ return wrapped.getAliases();
+ }
+
+ @Override
+ public Set<Annotation> getQualifiers() {
+ return wrapped.getQualifiers();
+ }
+
+ @Override
+ public String getAnalyzer() {
+ return wrapped.getAnalyzer();
+ }
+
+ @Override
+ public String getName() {
+ return wrapped.getName();
+ }
+
+ @Override
+ public String toString() {
+ return "InitializableWrappingInstanceBinding(" + wrapped.getService().getClass() + ")";
+ }
+
+ @Override
+ public InitializableWrappingInstanceBinding clone() {
+ return new InitializableWrappingInstanceBinding(this);
+ }
+ }
+}
\ No newline at end of file
diff --git a/incubator/cdi-inject-weld/src/main/java/org/glassfish/jersey/inject/weld/internal/inject/InitializableSupplierInstanceBinding.java b/incubator/cdi-inject-weld/src/main/java/org/glassfish/jersey/inject/weld/internal/inject/InitializableSupplierInstanceBinding.java
new file mode 100644
index 0000000..d99bf59
--- /dev/null
+++ b/incubator/cdi-inject-weld/src/main/java/org/glassfish/jersey/inject/weld/internal/inject/InitializableSupplierInstanceBinding.java
@@ -0,0 +1,227 @@
+/*
+ * Copyright (c) 2021 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.inject.weld.internal.inject;
+
+import org.glassfish.jersey.internal.inject.AliasBinding;
+import org.glassfish.jersey.internal.inject.Binding;
+import org.glassfish.jersey.internal.inject.DisposableSupplier;
+import org.glassfish.jersey.internal.inject.SupplierInstanceBinding;
+
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Type;
+import java.util.Set;
+import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.function.Supplier;
+
+/**
+ * Supplier instance binding to be created in the pre-initialization phase and initialized in runtime.
+ * @param <T> Type of the supplied service described by this injection binding.
+ */
+public class InitializableSupplierInstanceBinding<T>
+ extends MatchableBinding<Supplier<T>, InitializableSupplierInstanceBinding<T>>
+ implements Cloneable {
+
+ private final InitializableSupplier<T> supplier;
+
+ /**
+ * Creates a supplier as an instance.
+ *
+ * @param supplier service's instance.
+ */
+ public InitializableSupplierInstanceBinding(Supplier<T> supplier) {
+ this.supplier = DisposableSupplier.class.isInstance(supplier)
+ ? new InitializableDisposableSupplier<T>((DisposableSupplier<T>) supplier)
+ : new InitializableSupplier<T>(supplier);
+ if ("EmptyReferenceFactory".equals(supplier.getClass().getSimpleName())) {
+ this.supplier.init(supplier);
+ this.supplier.isReferencingFactory = true;
+ }
+ if ("InitializedReferenceFactory".equals(supplier.getClass().getSimpleName())) {
+ this.supplier.init(supplier);
+ this.supplier.isReferencingFactory = true;
+ }
+ T t = supplier.get();
+ }
+
+ public void init(Supplier<T> supplier) {
+ this.supplier.init(supplier);
+ }
+
+ public boolean isInit() {
+ return supplier.init.get();
+ }
+
+ /**
+ * Gets supplier's instance.
+ *
+ * @return supplier's instance.
+ */
+ public Supplier<T> getSupplier() {
+ return supplier;
+ }
+
+ public Supplier<T> getOriginalSupplier() {
+ if (supplier.originalSupplier == null) {
+ throw new IllegalStateException("Supplier must not be null");
+ }
+ return supplier.originalSupplier;
+ }
+
+ public static <T> InitializableSupplierInstanceBinding<T> from(SupplierInstanceBinding<T> binding) {
+ return new InitializableSupplierWrappingInstanceBinding(binding);
+ }
+
+ @Override
+ public InitializableSupplierInstanceBinding clone() {
+ throw new RuntimeException(new CloneNotSupportedException());
+ }
+
+ public Matching matches(SupplierInstanceBinding<T> other) {
+ return matches(this.getOriginalSupplier().getClass(), other.getSupplier().getClass(), other);
+ }
+
+ public Matching matches(InitializableSupplierInstanceBinding<T> other) {
+ return matches(this.getOriginalSupplier().getClass(), other.getSupplier().getClass(), other);
+ }
+
+ private Matching<InitializableSupplierInstanceBinding<T>> matches(
+ Class<?> originalSupplierClass, Class<?> otherSupplierClass, Binding other) {
+ final boolean matchesService = originalSupplierClass.equals(otherSupplierClass);
+ final Matching matching = matchesContracts(other);
+ if (matching.matchLevel == MatchLevel.FULL_CONTRACT && matchesService) {
+ matching.matchLevel = MatchLevel.SUPPLIER;
+ }
+ return matching;
+ }
+
+ @Override
+ protected MatchLevel bestMatchLevel() {
+ return MatchLevel.SUPPLIER;
+ }
+
+ private static class InitializableDisposableSupplier<T> extends InitializableSupplier<T> implements DisposableSupplier<T> {
+ private InitializableDisposableSupplier(DisposableSupplier<T> originalSupplier) {
+ super(originalSupplier);
+ }
+
+ @Override
+ public void dispose(T instance) {
+ ((DisposableSupplier) supplier).dispose(instance);
+ }
+ }
+
+ private static class InitializableSupplier<T> implements Supplier<T> {
+
+ private AtomicBoolean init = new AtomicBoolean(false);
+ protected Supplier<T> supplier;
+ protected final Supplier<T> originalSupplier;
+ private boolean isReferencingFactory = false;
+
+ private InitializableSupplier(Supplier<T> originalSupplier) {
+ this.originalSupplier = originalSupplier;
+ }
+
+ private void init(Supplier<T> supply) {
+ if (!init.getAndSet(true)) {
+ this.supplier = supply;
+ } else if (!isReferencingFactory && supplier != supply) {
+ throw new IllegalStateException("Multiple initialized for " + originalSupplier.getClass());
+ }
+ }
+
+ @Override
+ public T get() {
+ if (!init.get()) {
+ throw new IllegalStateException("Not initialized" + originalSupplier.getClass());
+ }
+ return supplier.get();
+ }
+
+ public boolean isInit() {
+ return init.get();
+ }
+ }
+
+ private static class InitializableSupplierWrappingInstanceBinding<T> extends InitializableSupplierInstanceBinding<T> {
+ private final SupplierInstanceBinding wrapped;
+ public InitializableSupplierWrappingInstanceBinding(SupplierInstanceBinding binding) {
+ super(binding.getSupplier());
+ wrapped = binding;
+ }
+
+ private InitializableSupplierWrappingInstanceBinding(InitializableSupplierWrappingInstanceBinding binding) {
+ super(binding.getOriginalSupplier());
+ wrapped = binding.wrapped;
+ }
+
+ @Override
+ public Class getImplementationType() {
+ return super.getImplementationType();
+ }
+
+ @Override
+ public Supplier getSupplier() {
+ return super.getSupplier();
+ }
+
+ @Override
+ public Class<? extends Annotation> getScope() {
+ return wrapped.getScope();
+ }
+
+ @Override
+ public Set<Type> getContracts() {
+ return wrapped.getContracts();
+ }
+
+ @Override
+ public Integer getRank() {
+ return wrapped.getRank();
+ }
+
+ @Override
+ public Set<AliasBinding> getAliases() {
+ return wrapped.getAliases();
+ }
+
+ @Override
+ public Set<Annotation> getQualifiers() {
+ return wrapped.getQualifiers();
+ }
+
+ @Override
+ public String getAnalyzer() {
+ return wrapped.getAnalyzer();
+ }
+
+ @Override
+ public String getName() {
+ return wrapped.getName();
+ }
+
+ @Override
+ public InitializableSupplierWrappingInstanceBinding clone() {
+ return new InitializableSupplierWrappingInstanceBinding(this);
+ }
+
+ @Override
+ public String toString() {
+ return "InitializableSupplierWrappingInstanceBinding(" + wrapped.getSupplier() + ")";
+ }
+ }
+
+}
diff --git a/incubator/cdi-inject-weld/src/main/java/org/glassfish/jersey/inject/weld/internal/inject/MatchableBinding.java b/incubator/cdi-inject-weld/src/main/java/org/glassfish/jersey/inject/weld/internal/inject/MatchableBinding.java
new file mode 100644
index 0000000..e6cd0bd
--- /dev/null
+++ b/incubator/cdi-inject-weld/src/main/java/org/glassfish/jersey/inject/weld/internal/inject/MatchableBinding.java
@@ -0,0 +1,135 @@
+/*
+ * Copyright (c) 2021 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.inject.weld.internal.inject;
+
+import org.glassfish.jersey.internal.inject.Binding;
+
+import java.lang.reflect.Type;
+import java.util.Set;
+
+/**
+ * A Binding to be able to be compared and matched in the runtime to be properly initialized.
+ *
+ * @param <T> Type of the bean described by this injection binding.
+ * @param <D> Concrete injection binding implementation type.
+ */
+public abstract class MatchableBinding<T, D extends MatchableBinding> extends Binding<T, D> {
+
+ protected abstract MatchLevel bestMatchLevel();
+
+ protected Matching<D> matches(Binding<?, ?> other) {
+ final Matching<D> matching = matchesContracts(other);
+ if (matching.matchLevel == MatchLevel.FULL_CONTRACT) {
+ if (getImplementationType().equals(other.getImplementationType())) {
+ matching.matchLevel = MatchLevel.IMPLEMENTATION;
+ }
+ }
+ return matching;
+ }
+
+ /**
+ * Return a Matching object that represents comparison between contracts of this binding and a given binding.
+ * The result contains a reference to this binding.
+ * @param other
+ * @return
+ */
+ public Matching<D> matchesContracts(Binding<?, ?> other) {
+ boolean atLeastOneMatch = false;
+ boolean allMatch = true;
+ final Set<Type> firstContracts = getContracts();
+ final Set<Type> secondContracts = other.getContracts();
+ final Set<Type> biggerContracts = firstContracts.size() < secondContracts.size() ? secondContracts : firstContracts;
+ final Set<Type> smallerContracts = firstContracts.size() < secondContracts.size() ? firstContracts : secondContracts;
+
+ for (Type thisType : biggerContracts) {
+ boolean aMatch = false;
+ for (Type otherType : smallerContracts) {
+ if (thisType.equals(otherType)) {
+ aMatch = true;
+ atLeastOneMatch = true;
+ break;
+ }
+ }
+ if (!aMatch) {
+ allMatch = false;
+ }
+ }
+ final MatchLevel matchLevel = atLeastOneMatch
+ ? (allMatch ? MatchLevel.FULL_CONTRACT : MatchLevel.PARTIAL_CONTRACT)
+ : MatchLevel.NONE;
+ final Matching<D> matching = new Matching<>((D) this, matchLevel);
+ return matching;
+ }
+
+ /**
+ * Matching object that represents the level of a match between two bindings. Contains a reference to a MatchableBinding
+ * whose instance was used to create the Matching object.
+ * @param <D> Concrete injection binding implementation type.
+ */
+ public static class Matching<D extends MatchableBinding> implements Comparable<Matching> {
+ private D binding;
+ protected MatchLevel matchLevel;
+
+ public static <D extends MatchableBinding> Matching<D> noneMatching() {
+ return new Matching<D>(null, MatchLevel.NONE);
+ }
+
+ protected Matching(D binding, MatchLevel matchLevel) {
+ this.binding = binding;
+ this.matchLevel = matchLevel;
+ }
+
+ @Override
+ public int compareTo(Matching other) {
+ return other.matchLevel.level - this.matchLevel.level;
+ }
+
+ public Matching better(Matching other) {
+ return compareTo(other) <= 0 ? this : other;
+ }
+
+ public boolean isBest() {
+ return matches() && matchLevel == binding.bestMatchLevel();
+ }
+
+ public boolean matches() {
+ return matchLevel.level > MatchLevel.NONE.level;
+ }
+
+ public D getBinding() {
+ return binding;
+ }
+ }
+
+ /**
+ * Internal granularity of a Matching.
+ */
+ protected static enum MatchLevel {
+ NONE(0),
+ PARTIAL_CONTRACT(1),
+ FULL_CONTRACT(2),
+ IMPLEMENTATION(3),
+ SUPPLIER(4);
+
+ private final int level;
+
+ MatchLevel(int level) {
+ this.level = level;
+ }
+ }
+}
+
diff --git a/incubator/cdi-inject-weld/src/main/java/org/glassfish/jersey/inject/weld/internal/injector/AbstractInjectionTarget.java b/incubator/cdi-inject-weld/src/main/java/org/glassfish/jersey/inject/weld/internal/injector/AbstractInjectionTarget.java
new file mode 100644
index 0000000..9b79ffa
--- /dev/null
+++ b/incubator/cdi-inject-weld/src/main/java/org/glassfish/jersey/inject/weld/internal/injector/AbstractInjectionTarget.java
@@ -0,0 +1,70 @@
+/*
+ * Copyright (c) 2021 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.inject.weld.internal.injector;
+
+import java.util.Set;
+
+import javax.enterprise.context.spi.CreationalContext;
+import javax.enterprise.inject.spi.InjectionPoint;
+import javax.enterprise.inject.spi.InjectionTarget;
+
+/**
+ * Abstract class which implements all methods from {@link InjectionTarget} by invoking the same methods on the delegate object.
+ * Useful super class to extend and override only the needed method.
+ *
+ * @param <T> type of the injection target.
+ * @author Petr Bouda
+ */
+abstract class AbstractInjectionTarget<T> implements InjectionTarget<T> {
+
+ /**
+ * Object on which all calls will be delegated.
+ *
+ * @return injection target.
+ */
+ abstract InjectionTarget<T> delegate();
+
+ @Override
+ public void inject(final T instance, final CreationalContext<T> ctx) {
+ delegate().inject(instance, ctx);
+ }
+
+ @Override
+ public void postConstruct(final T instance) {
+ delegate().postConstruct(instance);
+ }
+
+ @Override
+ public void preDestroy(final T instance) {
+ delegate().preDestroy(instance);
+ }
+
+ @Override
+ public T produce(final CreationalContext<T> ctx) {
+ return delegate().produce(ctx);
+ }
+
+ @Override
+ public void dispose(final T instance) {
+ delegate().dispose(instance);
+ }
+
+ @Override
+ public Set<InjectionPoint> getInjectionPoints() {
+ return delegate().getInjectionPoints();
+ }
+}
diff --git a/incubator/cdi-inject-weld/src/main/java/org/glassfish/jersey/inject/weld/internal/injector/CachedConstructorAnalyzer.java b/incubator/cdi-inject-weld/src/main/java/org/glassfish/jersey/inject/weld/internal/injector/CachedConstructorAnalyzer.java
new file mode 100644
index 0000000..2042642
--- /dev/null
+++ b/incubator/cdi-inject-weld/src/main/java/org/glassfish/jersey/inject/weld/internal/injector/CachedConstructorAnalyzer.java
@@ -0,0 +1,159 @@
+/*
+ * Copyright (c) 2021 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.inject.weld.internal.injector;
+
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Modifier;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+import java.util.Collection;
+import java.util.logging.Logger;
+
+import javax.enterprise.inject.InjectionException;
+import javax.inject.Inject;
+
+import org.glassfish.jersey.internal.LocalizationMessages;
+import org.glassfish.jersey.internal.util.collection.LazyValue;
+import org.glassfish.jersey.internal.util.collection.Value;
+import org.glassfish.jersey.internal.util.collection.Values;
+
+/**
+ * Processes a provided class and selects the valid constructor with the largest number of parameters. Constructor is cached
+ * for a later retrieve.
+ */
+public class CachedConstructorAnalyzer<T> {
+
+ private static final Logger LOGGER = Logger.getLogger(CachedConstructorAnalyzer.class.getName());
+
+ private final LazyValue<Constructor<T>> constructor;
+ private final Collection<Class<? extends Annotation>> resolverAnnotations;
+
+ /**
+ * Creates a new constructor analyzer which accepts the class that is analyzed.
+ *
+ * @param clazz analyzed class.
+ * @param annotations all annotations used for an injecting.
+ */
+ public CachedConstructorAnalyzer(Class<T> clazz, Collection<Class<? extends Annotation>> annotations) {
+ this.resolverAnnotations = annotations;
+ this.constructor = Values.lazy((Value<Constructor<T>>) () -> getConstructorInternal(clazz));
+ }
+
+ public Constructor<T> getConstructor() {
+ return constructor.get();
+ }
+
+ public boolean hasCompatibleConstructor() {
+ try {
+ return constructor.get() != null;
+ } catch (InjectionException ex) {
+ // Compatible constructor was not found.
+ return false;
+ }
+ }
+
+ /**
+ * Select the proper constructor of the given {@code clazz}.
+ *
+ * @return compatible and largest constructor.
+ */
+ @SuppressWarnings("unchecked")
+ private Constructor<T> getConstructorInternal(Class<T> clazz) {
+ if (clazz.isLocalClass()) {
+ throw new InjectionException(
+ LocalizationMessages.INJECTION_ERROR_LOCAL_CLASS_NOT_SUPPORTED(clazz.getName()));
+ }
+ if (clazz.isMemberClass() && !Modifier.isStatic(clazz.getModifiers())) {
+ throw new InjectionException(
+ LocalizationMessages.INJECTION_ERROR_NONSTATIC_MEMBER_CLASS_NOT_SUPPORTED(clazz.getName()));
+ }
+
+ // At this point, we simply need to find the constructor with the largest number of parameters
+ Constructor<?>[] constructors = AccessController.doPrivileged(
+ (PrivilegedAction<Constructor<?>[]>) clazz::getDeclaredConstructors);
+ Constructor<?> selected = null;
+ int selectedSize = 0;
+ int maxParams = -1;
+
+ for (Constructor<?> constructor : constructors) {
+ Class<?>[] params = constructor.getParameterTypes();
+ if (params.length >= maxParams && isCompatible(constructor)) {
+ if (params.length > maxParams) {
+ maxParams = params.length;
+ selectedSize = 0;
+ }
+
+ selected = constructor;
+ selectedSize++;
+ }
+ }
+
+ if (selectedSize == 0) {
+ throw new InjectionException(LocalizationMessages.INJECTION_ERROR_SUITABLE_CONSTRUCTOR_NOT_FOUND(clazz.getName()));
+ }
+
+ if (selectedSize > 1) {
+ // Found {0} constructors with {1} parameters in {2} class. Selecting the first found constructor: {3}
+ LOGGER.warning(LocalizationMessages.MULTIPLE_MATCHING_CONSTRUCTORS_FOUND(
+ selectedSize, maxParams, clazz.getName(), selected.toGenericString()));
+ }
+
+ return (Constructor<T>) selected;
+ }
+
+ /**
+ * Checks whether the constructor is valid for injection that means that all parameters has an injection annotation.
+ *
+ * @param constructor constructor to inject.
+ * @return True if element contains at least one inject annotation.
+ */
+ @SuppressWarnings("MagicConstant")
+ private boolean isCompatible(Constructor<?> constructor) {
+ if (constructor.getAnnotation(Inject.class) != null) {
+ // JSR-330 applicable
+ return true;
+ }
+
+ int paramSize = constructor.getParameterTypes().length;
+ if (paramSize != 0 && resolverAnnotations.isEmpty()) {
+ return false;
+ }
+
+ if (!Modifier.isPublic(constructor.getModifiers())) {
+ // return true for a default constructor, return false otherwise.
+ return paramSize == 0
+ && (constructor.getDeclaringClass().getModifiers()
+ & (Modifier.PUBLIC | Modifier.PROTECTED | Modifier.PRIVATE)) == constructor.getModifiers();
+ }
+
+ for (Annotation[] paramAnnotations : constructor.getParameterAnnotations()) {
+ boolean found = false;
+ for (Annotation paramAnnotation : paramAnnotations) {
+ if (resolverAnnotations.contains(paramAnnotation.annotationType())) {
+ found = true;
+ break;
+ }
+ }
+ if (!found) {
+ return false;
+ }
+ }
+
+ return true;
+ }
+}
diff --git a/incubator/cdi-inject-weld/src/main/java/org/glassfish/jersey/inject/weld/internal/injector/Collector.java b/incubator/cdi-inject-weld/src/main/java/org/glassfish/jersey/inject/weld/internal/injector/Collector.java
new file mode 100644
index 0000000..97077b2
--- /dev/null
+++ b/incubator/cdi-inject-weld/src/main/java/org/glassfish/jersey/inject/weld/internal/injector/Collector.java
@@ -0,0 +1,88 @@
+/*
+ * Copyright (c) 2021 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.inject.weld.internal.injector;
+
+import java.util.LinkedHashSet;
+import java.util.LinkedList;
+
+/**
+ * This class collects errors, and can then also produce a MultiException from those errors if necessary.
+ *
+ * @author John Wells (john.wells at oracle.com)
+ */
+class Collector {
+
+ private LinkedHashSet<Throwable> throwables;
+
+ /**
+ * Merges {@link MultiException} with all {@code throwables} registered in it.
+ *
+ * @param me {@code MultiException} to merge.
+ */
+ public void addMultiException(MultiException me) {
+ if (me == null) {
+ return;
+ }
+ if (throwables == null) {
+ throwables = new LinkedHashSet<>();
+ }
+
+ throwables.addAll(me.getErrors());
+ }
+
+ /**
+ * Adds a throwable to the list of throwables in this collector.
+ *
+ * @param th The throwable to add to the list.
+ */
+ public void addThrowable(Throwable th) {
+ if (th == null) {
+ return;
+ }
+ if (throwables == null) {
+ throwables = new LinkedHashSet<>();
+ }
+
+ if (th instanceof MultiException) {
+ throwables.addAll(((MultiException) th).getErrors());
+ } else {
+ throwables.add(th);
+ }
+ }
+
+ /**
+ * This method will throw if the list of throwables associated with this collector is not empty.
+ *
+ * @throws MultiException An exception with all the throwables found in this collector.
+ */
+ public void throwIfErrors() throws MultiException {
+ if (throwables == null || throwables.isEmpty()) {
+ return;
+ }
+
+ throw new MultiException(new LinkedList<>(throwables));
+ }
+
+ /**
+ * Returns true if this collector has errors.
+ *
+ * @return true if the collector has errors.
+ */
+ public boolean hasErrors() {
+ return ((throwables != null) && (!throwables.isEmpty()));
+ }
+}
diff --git a/incubator/cdi-inject-weld/src/main/java/org/glassfish/jersey/inject/weld/internal/injector/ContextInjectionResolverImpl.java b/incubator/cdi-inject-weld/src/main/java/org/glassfish/jersey/inject/weld/internal/injector/ContextInjectionResolverImpl.java
new file mode 100644
index 0000000..b494906
--- /dev/null
+++ b/incubator/cdi-inject-weld/src/main/java/org/glassfish/jersey/inject/weld/internal/injector/ContextInjectionResolverImpl.java
@@ -0,0 +1,151 @@
+/*
+ * Copyright (c) 2021 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.inject.weld.internal.injector;
+
+import java.lang.reflect.Type;
+import java.util.Set;
+import java.util.function.Supplier;
+
+import javax.enterprise.context.spi.CreationalContext;
+import javax.enterprise.inject.spi.Bean;
+import javax.enterprise.inject.spi.BeanManager;
+import javax.ws.rs.core.Context;
+import javax.ws.rs.core.GenericType;
+
+import org.glassfish.jersey.internal.inject.AbstractBinder;
+import org.glassfish.jersey.internal.inject.Bindings;
+import org.glassfish.jersey.internal.inject.ContextInjectionResolver;
+import org.glassfish.jersey.internal.inject.Injectee;
+import org.glassfish.jersey.internal.inject.InjecteeImpl;
+import org.glassfish.jersey.internal.inject.InjectionResolver;
+import org.glassfish.jersey.internal.util.ReflectionHelper;
+import org.glassfish.jersey.internal.util.collection.Cache;
+
+/**
+ * Injection resolver for {@link Context @Context} injection annotation.
+ *
+ * @author Petr Bouda
+ */
+public class ContextInjectionResolverImpl implements InjectionResolver<Context>, ContextInjectionResolver {
+
+ private Supplier<BeanManager> beanManager;
+
+ /**
+ * Creates a new {@link ContextInjectionResolver} with {@link BeanManager} to fetch Bean descriptors.
+ *
+ * @param beanManager current bean manager.
+ */
+ ContextInjectionResolverImpl(Supplier<BeanManager> beanManager) {
+ this.beanManager = beanManager;
+ }
+
+ private final Cache<Type, Bean<?>> descriptorCache = new Cache<>(key -> {
+ Set<Bean<?>> beans = beanManager.get().getBeans(key);
+ if (beans.isEmpty()) {
+ return null;
+ }
+ return beans.iterator().next();
+ });
+
+ @Override
+ public Object resolve(Injectee injectee) {
+ Injectee newInjectee = injectee;
+ if (injectee.isFactory()) {
+ newInjectee = getFactoryInjectee(injectee, ReflectionHelper.getTypeArgument(injectee.getRequiredType(), 0));
+ }
+
+ Bean<?> bean = descriptorCache.apply(newInjectee.getRequiredType());
+
+ if (bean != null) {
+ CreationalContext ctx = beanManager.get().createCreationalContext(bean);
+ Object result = bean.create(ctx);
+
+ if (injectee.isFactory()) {
+ return (Supplier<Object>) () -> result;
+ } else {
+ return result;
+ }
+ }
+ return null;
+ }
+
+ @Override
+ public boolean isConstructorParameterIndicator() {
+ return true;
+ }
+
+ @Override
+ public boolean isMethodParameterIndicator() {
+ return false;
+ }
+
+ @Override
+ public Class<Context> getAnnotation() {
+ return Context.class;
+ }
+
+ /**
+ * Context injection resolver binder.
+ */
+ public static final class Binder extends AbstractBinder {
+
+ private Supplier<BeanManager> beanManager;
+
+ public Binder(Supplier<BeanManager> beanManager) {
+ this.beanManager = beanManager;
+ }
+
+ @Override
+ @SuppressWarnings("unchecked")
+ protected void configure() {
+ ContextInjectionResolverImpl resolver = new ContextInjectionResolverImpl(beanManager);
+
+ /*
+ * Binding for CDI, without this binding JerseyInjectionTarget wouldn't know about the ContextInjectionTarget and
+ * injection into fields would be disabled.
+ */
+ bind(resolver)
+ .to(new GenericType<InjectionResolver<Context>>() {})
+ .to(ContextInjectionResolver.class);
+
+ /*
+ * Binding for Jersey, without this binding Jersey wouldn't put together ContextInjectionResolver and
+ * DelegatedInjectionValueParamProvider and therefore injection into resource method would be disabled.
+ */
+ bind(Bindings.service(resolver))
+ .to(new GenericType<InjectionResolver<Context>>() {})
+ .to(ContextInjectionResolver.class);
+ }
+ }
+
+ private Injectee getFactoryInjectee(Injectee injectee, Type requiredType) {
+ return new RequiredTypeOverridingInjectee(injectee, requiredType);
+ }
+
+ private static class RequiredTypeOverridingInjectee extends InjecteeImpl {
+ private RequiredTypeOverridingInjectee(Injectee injectee, Type requiredType) {
+ setFactory(injectee.isFactory());
+ setInjecteeClass(injectee.getInjecteeClass());
+ setInjecteeDescriptor(injectee.getInjecteeDescriptor());
+ setOptional(injectee.isOptional());
+ setParent(injectee.getParent());
+ setPosition(injectee.getPosition());
+ setRequiredQualifiers(injectee.getRequiredQualifiers());
+ setRequiredType(requiredType);
+ }
+ }
+}
diff --git a/incubator/cdi-inject-weld/src/main/java/org/glassfish/jersey/inject/weld/internal/injector/InjectionUtils.java b/incubator/cdi-inject-weld/src/main/java/org/glassfish/jersey/inject/weld/internal/injector/InjectionUtils.java
new file mode 100644
index 0000000..946db4d
--- /dev/null
+++ b/incubator/cdi-inject-weld/src/main/java/org/glassfish/jersey/inject/weld/internal/injector/InjectionUtils.java
@@ -0,0 +1,311 @@
+/*
+ * Copyright (c) 2021 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.inject.weld.internal.injector;
+
+import java.lang.annotation.Annotation;
+import java.lang.reflect.AnnotatedElement;
+import java.lang.reflect.Field;
+import java.lang.reflect.Member;
+import java.lang.reflect.Modifier;
+import java.lang.reflect.ParameterizedType;
+import java.lang.reflect.Type;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.LinkedHashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.function.Function;
+import java.util.stream.Collectors;
+
+import javax.enterprise.inject.spi.Bean;
+import javax.inject.Named;
+import javax.inject.Provider;
+
+import org.glassfish.jersey.internal.inject.Injectee;
+import org.glassfish.jersey.internal.inject.InjecteeImpl;
+import org.glassfish.jersey.internal.inject.InjectionResolver;
+import org.glassfish.jersey.internal.util.Pretty;
+import org.glassfish.jersey.internal.util.collection.ImmutableCollectors;
+
+/**
+ * Utility class for processing of an injection.
+ *
+ * @author Petr Bouda
+ */
+public final class InjectionUtils {
+
+ /**
+ * Forbids the creation of {@link InjectionUtils} instance.
+ */
+ private InjectionUtils() {
+ }
+
+ /**
+ * Just injects the thing, doesn't try to do anything else
+ *
+ * @param injectMe the object to inject into.
+ * @param bean information about the injected instance.
+ * @param resolvers all injection resolvers registered in the application.
+ * @param proxyResolver object which is able to create a proxy.
+ * @param <T> type of the injected instance.
+ */
+ static <T> void justInject(T injectMe, Bean<T> bean, Map<Field, InjectionResolver> resolvers,
+ JerseyProxyResolver proxyResolver) {
+ if (injectMe == null) {
+ throw new IllegalArgumentException();
+ }
+
+ for (Map.Entry<Field, InjectionResolver> entry : resolvers.entrySet()) {
+ Field field = entry.getKey();
+ InjectionResolver resolver = entry.getValue();
+ Injectee injectee = InjectionUtils.getFieldInjectee(bean, field);
+
+ Object resolvedValue;
+ if (injectee.isProvider()) {
+ resolvedValue = (Provider<Object>) () -> resolver.resolve(injectee);
+ } else if (proxyResolver.isProxiable(injectee)) {
+ resolvedValue = proxyResolver.proxy(injectee, resolver);
+ } else {
+ resolvedValue = resolver.resolve(injectee);
+ }
+
+ try {
+ ReflectionUtils.setField(field, injectMe, resolvedValue);
+ } catch (MultiException me) {
+ throw me;
+ } catch (Throwable th) {
+ throw new MultiException(th);
+ }
+ }
+ }
+
+ /**
+ * Returns the injectee for a field.
+ *
+ * @param bean bean in which the field is placed.
+ * @param field the field to analyze.
+ * @return the list (in order) of parameters to the constructor.
+ */
+ private static Injectee getFieldInjectee(Bean<?> bean, Field field) {
+ Set<Annotation> annotations = Arrays.stream(field.getAnnotations())
+ .collect(ImmutableCollectors.toImmutableSet());
+
+ Type adjustedType = ReflectionUtils.resolveField(bean.getBeanClass(), field);
+
+ InjecteeImpl injectee = new InjecteeImpl();
+ injectee.setParentClassScope(bean.getScope());
+
+ if (isProvider(adjustedType)) {
+ ParameterizedType paramType = (ParameterizedType) adjustedType;
+ injectee.setRequiredType(paramType.getActualTypeArguments()[0]);
+ injectee.setProvider(true);
+ } else {
+ injectee.setRequiredType(adjustedType);
+ }
+
+ injectee.setParent(field);
+ injectee.setRequiredQualifiers(getFieldAdjustedQualifierAnnotations(field, annotations));
+ return injectee;
+ }
+
+ public static boolean isProvider(Type type) {
+ if (type instanceof ParameterizedType) {
+ ParameterizedType paramType = (ParameterizedType) type;
+ return Provider.class.isAssignableFrom((Class<?>) paramType.getRawType());
+ }
+
+ return false;
+ }
+
+ private static Set<Annotation> getFieldAdjustedQualifierAnnotations(Field field, Set<Annotation> qualifiers) {
+ Named n = field.getAnnotation(Named.class);
+ if (n == null || !"".equals(n.value())) {
+ return qualifiers;
+ }
+
+ HashSet<Annotation> retVal = new HashSet<>();
+ for (Annotation qualifier : qualifiers) {
+ if (qualifier.annotationType().equals(Named.class)) {
+ retVal.add(new NamedImpl(field.getName()));
+ } else {
+ retVal.add(qualifier);
+ }
+ }
+
+ return retVal;
+ }
+
+ /**
+ * Gets the fields from the given class and analyzer. Checks service output.
+ *
+ * @param clazz the non-null impl class.
+ * @param injectAnnotations all annotations which can be used to inject a value.
+ * @param errors for gathering errors. @return a non-null set (even in error cases, check the collector).
+ */
+ static Set<Field> getFields(Class<?> clazz, Set<? extends Class<?>> injectAnnotations, Collector errors) {
+ Set<Field> retVal;
+
+ try {
+ retVal = getFieldsInternal(clazz, injectAnnotations, errors);
+ } catch (MultiException me) {
+ errors.addMultiException(me);
+ return Collections.emptySet();
+ } catch (Throwable th) {
+ errors.addThrowable(th);
+ return Collections.emptySet();
+ }
+
+ return retVal;
+ }
+
+ /**
+ * Will find all the initialize fields in the class.
+ *
+ * @param clazz the class to search for fields
+ * @param injectAnnotations all annotations which can be used to inject a value.
+ * @param errors the error collector
+ * @return A non-null but possibly empty set of initializer fields
+ */
+ private static Set<Field> getFieldsInternal(Class<?> clazz, Set<? extends Class<?>> injectAnnotations, Collector errors) {
+ Set<Field> retVal = new LinkedHashSet<>();
+
+ for (Field field : ReflectionUtils.getAllFields(clazz)) {
+ if (!hasInjectAnnotation(field, injectAnnotations)) {
+ // Not an initializer field
+ continue;
+ }
+
+ if (!isProperField(field)) {
+ errors.addThrowable(new IllegalArgumentException("The field " + Pretty.field(field)
+ + " may not be static, final or have an Annotation type"));
+ continue;
+ }
+
+ retVal.add(field);
+ }
+
+ return retVal;
+ }
+
+ /**
+ * Checks whether an annotated element has any annotation that was used for the injection.
+ *
+ * @param annotated the annotated element.
+ * @param injectAnnotations all annotations which can be used to inject a value.
+ * @return True if element contains at least one inject annotation.
+ */
+ private static boolean hasInjectAnnotation(AnnotatedElement annotated, Set<? extends Class<?>> injectAnnotations) {
+ for (Annotation annotation : annotated.getAnnotations()) {
+ if (injectAnnotations.contains(annotation.annotationType())) {
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ private static boolean isProperField(Field field) {
+ if (isStatic(field) || isFinal(field)) {
+ return false;
+ }
+
+ Class<?> type = field.getType();
+ return !type.isAnnotation();
+ }
+
+ /**
+ * Returns true if the underlying member is static.
+ *
+ * @param member The non-null member to test.
+ * @return true if the member is static.
+ */
+ private static boolean isStatic(Member member) {
+ int modifiers = member.getModifiers();
+ return ((modifiers & Modifier.STATIC) != 0);
+ }
+
+ /**
+ * Returns true if the underlying member is abstract.
+ *
+ * @param member The non-null member to test.
+ * @return true if the member is abstract.
+ */
+ private static boolean isFinal(Member member) {
+ int modifiers = member.getModifiers();
+ return ((modifiers & Modifier.FINAL) != 0);
+ }
+
+ /**
+ * Returns all annotations that can be managed using registered and provided {@link InjectionResolver injection resolvers}.
+ *
+ * @param resolvers all registered resolvers.
+ * @return all possible injection annotations.
+ */
+ @SuppressWarnings("unchecked")
+ public static Collection<Class<? extends Annotation>> getInjectAnnotations(Collection<InjectionResolver> resolvers) {
+ List<Class<? extends Annotation>> annotations = new ArrayList<>();
+ for (InjectionResolver resolver : resolvers) {
+ annotations.add(resolver.getAnnotation());
+ }
+ return annotations;
+ }
+
+ /**
+ * Assigns {@link InjectionResolver} to every {@link AnnotatedElement} provided as a method parameter. Injection resolver
+ * will be used for fetching the proper value during the injection processing.
+ *
+ * @param annotatedElements all annotated elements from the class which this injector belongs to.
+ * @param resolvers all registered injection resolvers.
+ * @param <A> type of the annotated elements.
+ * @return immutable map of all fields along with injection resolvers using that can be injected.
+ */
+ static <A extends AnnotatedElement> Map<A, InjectionResolver> mapElementToResolver(Set<A> annotatedElements,
+ Map<? extends Class<?>, InjectionResolver> resolvers) {
+
+ Map<A, InjectionResolver> mappedElements = new HashMap<>();
+ for (A element : annotatedElements) {
+ mappedElements.put(element, findResolver(resolvers, element));
+ }
+ return mappedElements;
+ }
+
+ static InjectionResolver findResolver(Map<? extends Class<?>, InjectionResolver> resolvers, AnnotatedElement element) {
+ for (Annotation annotation : element.getAnnotations()) {
+ InjectionResolver injectionResolver = resolvers.get(annotation.annotationType());
+ if (injectionResolver != null) {
+ return injectionResolver;
+ }
+ }
+
+ return null;
+ }
+
+ /**
+ * Creates a map from resolvers where the annotation that is handled by resolver is a key and resolver itself is value.
+ *
+ * @param resolvers collection of resolvers.
+ * @return map resolver annotation to resolver.
+ */
+ static Map<? extends Class<?>, InjectionResolver> mapAnnotationToResolver(Collection<InjectionResolver> resolvers) {
+ return resolvers.stream().collect(Collectors.toMap(InjectionResolver::getAnnotation, Function.identity()));
+ }
+}
diff --git a/incubator/cdi-inject-weld/src/main/java/org/glassfish/jersey/inject/weld/internal/injector/JerseyClientCreationalContext.java b/incubator/cdi-inject-weld/src/main/java/org/glassfish/jersey/inject/weld/internal/injector/JerseyClientCreationalContext.java
new file mode 100644
index 0000000..529b94f
--- /dev/null
+++ b/incubator/cdi-inject-weld/src/main/java/org/glassfish/jersey/inject/weld/internal/injector/JerseyClientCreationalContext.java
@@ -0,0 +1,155 @@
+/*
+ * Copyright (c) 2021 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.inject.weld.internal.injector;
+
+import javax.enterprise.context.spi.Contextual;
+import javax.enterprise.context.spi.CreationalContext;
+
+import org.glassfish.jersey.inject.weld.internal.managed.CdiClientInjectionManager;
+import org.jboss.weld.construction.api.AroundConstructCallback;
+import org.jboss.weld.context.api.ContextualInstance;
+import org.jboss.weld.contexts.CreationalContextImpl;
+import org.jboss.weld.injection.spi.ResourceReference;
+import org.jboss.weld.interceptor.proxy.InterceptionContext;
+
+import java.util.List;
+
+/**
+ * Jersey implementation of CreationalContext holding an instance of the client InjectionManager.
+ * Should be used on the client side only. Wraps the original context.
+ * @param <T> the class of the creational context.
+ */
+public class JerseyClientCreationalContext<T> extends CreationalContextImpl<T> {
+
+ private final CreationalContextImpl<T> wrapped;
+ private CdiClientInjectionManager injectionManager = null;
+
+ public JerseyClientCreationalContext(CreationalContextImpl<T> wrapped) {
+ super(wrapped.getContextual());
+ this.wrapped = wrapped;
+ }
+
+ @Override
+ public <S> CreationalContextImpl<S> getCreationalContext(Contextual<S> contextual) {
+ return new JerseyClientCreationalContext<>(wrapped.getCreationalContext(contextual))
+ .setInjectionManager(injectionManager);
+ }
+
+ public <S> CreationalContextImpl<S> getProducerReceiverCreationalContext(Contextual<S> contextual) {
+ return new JerseyClientCreationalContext<>(wrapped.getProducerReceiverCreationalContext(contextual))
+ .setInjectionManager(injectionManager);
+ }
+
+ public <S> S getIncompleteInstance(Contextual<S> bean) {
+ return wrapped.getIncompleteInstance(bean);
+ }
+
+ public boolean containsIncompleteInstance(Contextual<?> bean) {
+ return wrapped.containsIncompleteInstance(bean);
+ }
+
+ public void addDependentInstance(ContextualInstance<?> contextualInstance) {
+ wrapped.addDependentInstance(contextualInstance);
+ }
+
+ public void release() {
+ wrapped.release();
+ }
+
+ public void release(Contextual<T> contextual, T instance) {
+ wrapped.release(contextual, instance);
+ }
+
+ /**
+ * @return the parent {@link CreationalContext} or null if there isn't any parent.
+ */
+ public CreationalContextImpl<?> getParentCreationalContext() {
+ return wrapped.getParentCreationalContext();
+ }
+
+ /**
+ * Returns an unmodifiable list of dependent instances.
+ */
+ public List<ContextualInstance<?>> getDependentInstances() {
+ return wrapped.getDependentInstances();
+ }
+
+ /**
+ * Register a {@link ResourceReference} as a dependency. {@link ResourceReference#release()} will be called on every {@link ResourceReference} once this
+ * {@link CreationalContext} instance is released.
+ */
+ public void addDependentResourceReference(ResourceReference<?> resourceReference) {
+ wrapped.addDependentResourceReference(resourceReference);
+ }
+
+ /**
+ * Destroys dependent instance
+ *
+ * @param instance
+ * @return true if the instance was destroyed, false otherwise
+ */
+ public boolean destroyDependentInstance(T instance) {
+ return wrapped.destroyDependentInstance(instance);
+ }
+
+ /**
+ * @return the {@link Contextual} for which this {@link CreationalContext} is created.
+ */
+ public Contextual<T> getContextual() {
+ return wrapped.getContextual();
+ }
+
+ public List<AroundConstructCallback<T>> getAroundConstructCallbacks() {
+ return wrapped.getAroundConstructCallbacks();
+ }
+
+ @Override
+ public void setConstructorInterceptionSuppressed(boolean value) {
+ wrapped.setConstructorInterceptionSuppressed(value);
+ }
+
+ @Override
+ public boolean isConstructorInterceptionSuppressed() {
+ return wrapped.isConstructorInterceptionSuppressed();
+ }
+
+ @Override
+ public void registerAroundConstructCallback(AroundConstructCallback<T> callback) {
+ wrapped.registerAroundConstructCallback(callback);
+ }
+
+ /**
+ *
+ * @return the interception context used for Weld-managed AroundConstruct interceptors or <code>null</code> if no such interceptors were applied
+ */
+ public InterceptionContext getAroundConstructInterceptionContext() {
+ return wrapped.getAroundConstructInterceptionContext();
+ }
+
+ public void setAroundConstructInterceptionContext(InterceptionContext aroundConstructInterceptionContext) {
+ wrapped.setAroundConstructInterceptionContext(aroundConstructInterceptionContext);
+ }
+
+ public JerseyClientCreationalContext setInjectionManager(CdiClientInjectionManager injectionManager) {
+ this.injectionManager = injectionManager;
+ return this;
+ }
+
+ public CdiClientInjectionManager getInjectionManager() {
+ return injectionManager;
+ }
+}
diff --git a/incubator/cdi-inject-weld/src/main/java/org/glassfish/jersey/inject/weld/internal/injector/JerseyConstructorInjectionPoint.java b/incubator/cdi-inject-weld/src/main/java/org/glassfish/jersey/inject/weld/internal/injector/JerseyConstructorInjectionPoint.java
new file mode 100644
index 0000000..d2677ac
--- /dev/null
+++ b/incubator/cdi-inject-weld/src/main/java/org/glassfish/jersey/inject/weld/internal/injector/JerseyConstructorInjectionPoint.java
@@ -0,0 +1,176 @@
+/*
+ * Copyright (c) 2021 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.inject.weld.internal.injector;
+
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Parameter;
+import java.lang.reflect.ParameterizedType;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+import java.util.Map;
+import java.util.function.Supplier;
+import java.util.stream.Collectors;
+
+import javax.enterprise.context.spi.CreationalContext;
+import javax.enterprise.inject.spi.Bean;
+import javax.inject.Provider;
+
+import org.glassfish.jersey.internal.inject.Injectee;
+import org.glassfish.jersey.internal.inject.InjecteeImpl;
+import org.glassfish.jersey.internal.inject.InjectionResolver;
+
+import org.jboss.weld.annotated.enhanced.EnhancedAnnotatedConstructor;
+import org.jboss.weld.injection.ConstructorInjectionPoint;
+import org.jboss.weld.injection.InjectionPointFactory;
+import org.jboss.weld.injection.ParameterInjectionPoint;
+import org.jboss.weld.manager.BeanManagerImpl;
+
+/**
+ * Class that creates a new instance using the provided constructor, selects and injects the values.
+ *
+ * @author Petr Bouda
+ */
+public class JerseyConstructorInjectionPoint<T> extends ConstructorInjectionPoint<T> {
+
+ private final JerseyProxyResolver proxyResolver = new JerseyProxyResolver();
+
+ private List<Supplier<Object>> cachedSuppliers;
+
+ private Object[] cachedProxies;
+
+ /**
+ * Creates a new constructor injection point suitable for Jersey components.
+ *
+ * @param constructor resolved constructor that can be injected using Jersey.
+ * @param bean bean descriptor dedicated to the parent class.
+ * @param manager current bean manager.
+ * @param resolvers all registered resolvers.
+ */
+ public JerseyConstructorInjectionPoint(EnhancedAnnotatedConstructor<T> constructor, Bean<T> bean, BeanManagerImpl manager,
+ Collection<InjectionResolver> resolvers) {
+ super(constructor, null, constructor.getJavaClass(), InjectionPointFactory.instance(), manager);
+
+ List<InjecteeToSupplier> valueSuppliers =
+ createValueSuppliers(constructor.getJavaMember(), getParameterInjectionPoints(), resolvers);
+
+ /*
+ * Caches either created proxies if the component class is not RequestScoped or caches the supplier that just create
+ * values every component creates.
+ */
+ if (proxyResolver.isProxiable(bean.getScope())) {
+ this.cachedProxies = generateProxies(valueSuppliers);
+ } else {
+ this.cachedSuppliers = valueSuppliers.stream()
+ .map(is -> is.supplier)
+ .collect(Collectors.toList());
+ }
+ }
+
+ /**
+ * Helper method for getting the current parameter values from a list of annotated parameters.
+ *
+ * @param manager The Bean manager
+ * @return The object array of looked up values
+ */
+ public Object[] getParameterValues(BeanManagerImpl manager, CreationalContext<?> ctx, CreationalContext<?> ctxTransient) {
+ if (cachedProxies == null) {
+ return generateValues(cachedSuppliers);
+ } else {
+ return cachedProxies;
+ }
+ }
+
+ private Object[] generateValues(List<Supplier<Object>> suppliers) {
+ Object[] parameterValues = new Object[getParameterInjectionPoints().size()];
+ for (int i = 0; i < parameterValues.length; i++) {
+ parameterValues[i] = suppliers.get(i).get();
+ }
+ return parameterValues;
+ }
+
+ private Object[] generateProxies(List<InjecteeToSupplier> suppliers) {
+ Object[] proxies = new Object[suppliers.size()];
+ for (int i = 0; i < proxies.length; i++) {
+ InjecteeToSupplier injecteeToSupplier = suppliers.get(i);
+ if (injecteeToSupplier.injectee.isProvider()) {
+ proxies[i] = new Provider<Object>() {
+ @Override
+ public Object get() {
+ return injecteeToSupplier.supplier.get();
+ }
+ };
+ } else {
+ proxies[i] = proxyResolver.noCachedProxy(injecteeToSupplier.injectee, injecteeToSupplier.supplier);
+ }
+ }
+ return proxies;
+ }
+
+ /**
+ * Maps the parameters of the selected constructor to the injection resolver.
+ *
+ * @param params all parameters of a constructor.
+ * @param resolvers registered injection resolvers.
+ * @return map of the parameter to injection resolver.
+ */
+ private List<InjecteeToSupplier> createValueSuppliers(Constructor<T> constructor,
+ List<ParameterInjectionPoint<?, T>> params, Collection<InjectionResolver> resolvers) {
+
+ List<InjecteeToSupplier> suppliers = new ArrayList<>();
+ Map<? extends Class<?>, InjectionResolver> injectAnnotations = InjectionUtils.mapAnnotationToResolver(resolvers);
+ for (int i = 0; i < params.size(); i++) {
+ Parameter parameter = params.get(i).getAnnotated().getJavaParameter();
+ InjectionResolver resolver = InjectionUtils.findResolver(injectAnnotations, parameter);
+ Injectee injectee = parameterToInjectee(constructor, parameter, i);
+// if (!Class.class.isInstance(injectee.getRequiredType()) || ((Class) injectee.getRequiredType()).isInterface()) {
+ suppliers.add(new InjecteeToSupplier(injectee, () -> resolver.resolve(injectee)));
+// }
+ }
+
+ return suppliers;
+ }
+
+ private Injectee parameterToInjectee(Constructor<T> constructor, Parameter parameter, int position) {
+ InjecteeImpl injectee = new InjecteeImpl();
+ injectee.setParent(constructor);
+ if (parameter.getParameterizedType() instanceof ParameterizedType
+ && InjectionUtils.isProvider(parameter.getParameterizedType())) {
+ ParameterizedType paramType = (ParameterizedType) parameter.getParameterizedType();
+ injectee.setRequiredType(paramType.getActualTypeArguments()[0]);
+ injectee.setProvider(true);
+ } else {
+ injectee.setRequiredType(parameter.getType());
+ }
+ injectee.setPosition(position);
+ return injectee;
+ }
+
+ /**
+ * Holder for Injectee and Supplier types. Internal class.
+ */
+ private static class InjecteeToSupplier {
+
+ private final Injectee injectee;
+ private final Supplier<Object> supplier;
+
+ private InjecteeToSupplier(Injectee injectee, Supplier<Object> supplier) {
+ this.injectee = injectee;
+ this.supplier = supplier;
+ }
+ }
+}
diff --git a/incubator/cdi-inject-weld/src/main/java/org/glassfish/jersey/inject/weld/internal/injector/JerseyInjectionTarget.java b/incubator/cdi-inject-weld/src/main/java/org/glassfish/jersey/inject/weld/internal/injector/JerseyInjectionTarget.java
new file mode 100644
index 0000000..e5702c0
--- /dev/null
+++ b/incubator/cdi-inject-weld/src/main/java/org/glassfish/jersey/inject/weld/internal/injector/JerseyInjectionTarget.java
@@ -0,0 +1,342 @@
+/*
+ * Copyright (c) 2021 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.inject.weld.internal.injector;
+
+import java.lang.reflect.Modifier;
+import java.util.Collection;
+import java.util.List;
+
+import javax.enterprise.context.Dependent;
+import javax.ws.rs.WebApplicationException;
+
+import javax.enterprise.context.spi.CreationalContext;
+import javax.enterprise.inject.InjectionException;
+import javax.enterprise.inject.spi.Bean;
+import javax.enterprise.inject.spi.Decorator;
+import javax.enterprise.inject.spi.InjectionTarget;
+import javax.enterprise.inject.spi.Interceptor;
+
+import org.glassfish.jersey.inject.weld.internal.bean.BeanHelper;
+import org.glassfish.jersey.inject.weld.internal.bean.JerseyBean;
+import org.glassfish.jersey.internal.inject.InjectionResolver;
+import org.glassfish.jersey.internal.util.collection.LazyValue;
+import org.glassfish.jersey.internal.util.collection.Value;
+import org.glassfish.jersey.internal.util.collection.Values;
+
+import org.jboss.weld.annotated.enhanced.EnhancedAnnotatedConstructor;
+import org.jboss.weld.annotated.enhanced.EnhancedAnnotatedMethod;
+import org.jboss.weld.annotated.enhanced.EnhancedAnnotatedType;
+import org.jboss.weld.bean.CustomDecoratorWrapper;
+import org.jboss.weld.bean.DecoratorImpl;
+import org.jboss.weld.bean.proxy.ProxyInstantiator;
+import org.jboss.weld.injection.producer.AbstractInstantiator;
+import org.jboss.weld.injection.producer.BasicInjectionTarget;
+import org.jboss.weld.injection.producer.ConstructorInterceptionInstantiator;
+import org.jboss.weld.injection.producer.DefaultInstantiator;
+import org.jboss.weld.injection.producer.Instantiator;
+import org.jboss.weld.injection.producer.InterceptionModelInitializer;
+import org.jboss.weld.injection.producer.InterceptorApplyingInstantiator;
+import org.jboss.weld.injection.producer.SubclassDecoratorApplyingInstantiator;
+import org.jboss.weld.injection.producer.SubclassedComponentInstantiator;
+import org.jboss.weld.interceptor.spi.model.InterceptionModel;
+import org.jboss.weld.logging.BeanLogger;
+import org.jboss.weld.resources.ClassTransformer;
+import org.jboss.weld.util.reflection.Formats;
+
+/**
+ * Wrapper for {@link InjectionTarget} that implements the functionality of injecting using JAX-RS annotations into provided
+ * instances. {@code Delegate} is a original {@code InjectionTarget} which is able to inject other fields/parameters which
+ * are managed by CDI.
+ * <p>
+ * Implementation is also able create with custom {@code jerseyConstructor} if it is provided. This functionality allows override
+ * default instantiator and use the Jersey-specific one.
+ */
+public class JerseyInjectionTarget<T> extends BasicInjectionTarget<T> {
+
+ private final Bean<T> bean;
+ private final Class<T> clazz;
+ private final LazyValue<JerseyInstanceInjector<T>> injector;
+ private final EnhancedAnnotatedType<T> enhancedAnnotatedType;
+ private Collection<InjectionResolver> resolvers;
+ private BasicInjectionTarget delegate; // for managed beans the initializeAfterBeanDiscovery is called for it
+ private final Instantiator<T> instantiator;
+
+ /**
+ * Creates a new injection target which is able to delegate an injection to {@code delegate injection target} and inject
+ * the fields that are Jersey-specific. The resolvers must be set later on. CDI will select its own constructor.
+ *
+ * @param delegate CDI specific injection target.
+ * @param clazz class that will be scanned and injected.
+ */
+ public JerseyInjectionTarget(BasicInjectionTarget<T> delegate, Class<T> clazz) {
+ this(delegate, delegate.getBean(), clazz, null);
+ }
+
+ /**
+ * Creates a new injection target which is able to delegate an injection to {@code delegate injection target} and inject
+ * the fields that are Jersey-specific. CDI will select its own constructor.
+ *
+ * @param delegate CDI specific injection target.
+ * @param bean bean which this injection target belongs to.
+ * @param clazz class that will be scanned and injected.
+ * @param resolvers all resolvers that can provide a valued for Jersey-specific injection.
+ */
+ public JerseyInjectionTarget(BasicInjectionTarget<T> delegate, Bean<T> bean, Class<T> clazz,
+ Collection<InjectionResolver> resolvers) {
+ this(BeanHelper.createEnhancedAnnotatedType(delegate), delegate, bean, clazz, resolvers, delegate.getInstantiator());
+ this.delegate = delegate;
+ setInstantiator(this.instantiator);
+ }
+
+ /**
+ * Creates a new injection target which is able to delegate an injection to {@code delegate injection target} and inject
+ * the fields that are Jersey-specific. This method accepts custom instantiator, if the instantiator is {@code null}
+ * default one is created.
+ *
+ * @param annotatedType resolved type of the registered bean.
+ * @param delegate CDI specific injection target.
+ * @param bean bean which this injection target belongs to.
+ * @param clazz class that will be scanned and injected.
+ * @param resolvers all resolvers that can provide a valued for Jersey-specific injection.
+ * @param instantiator default instantiator.
+ */
+ public JerseyInjectionTarget(EnhancedAnnotatedType<T> annotatedType, BasicInjectionTarget<T> delegate, Bean<T> bean,
+ Class<T> clazz, Collection<InjectionResolver> resolvers, Instantiator<T> instantiator) {
+ super(annotatedType,
+ bean,
+ delegate.getBeanManager(),
+ delegate.getInjector(),
+ delegate.getLifecycleCallbackInvoker(),
+ JerseyBean.class.isInstance(bean)
+ ? new JerseyTwofoldInstantiator<T>((AbstractInstantiator<T>) instantiator)
+ : instantiator);
+
+ this.bean = bean;
+ this.enhancedAnnotatedType = annotatedType;
+ this.clazz = clazz;
+ this.resolvers = resolvers;
+ this.injector = Values.lazy((Value<JerseyInstanceInjector<T>>) () -> new JerseyInstanceInjector<>(bean, this.resolvers));
+ this.delegate = null;
+ this.instantiator = getInstantiator();
+ setInstantiator(this.instantiator);
+ }
+
+ @Override
+ protected void checkDelegateInjectionPoints() {
+ if (getAnnotatedType().getAnnotation(javax.decorator.Decorator.class) == null) {
+ super.checkDelegateInjectionPoints();
+ }
+ }
+
+ @Override
+ public void inject(T instance, CreationalContext<T> ctx) {
+ /*
+ * If an instance contains any fields which be injected by Jersey then Jersey attempts to inject them using annotations
+ * retrieves from registered InjectionResolvers.
+ */
+ try {
+ injector.get().inject(instance);
+ } catch (WebApplicationException wae) {
+ throw wae;
+ } catch (Throwable cause) {
+ throw new InjectionException(
+ "Exception occurred during Jersey/JAX-RS annotations processing in the class: " + clazz, cause);
+ }
+
+ /*
+ * The rest of the fields (annotated by @Inject) are injected using CDI.
+ */
+ super.inject(instance, ctx);
+ }
+
+ /**
+ * Copied method from the parent class because of a custom type of {@link Instantiator} is used in this implementation.
+ *
+ * @param annotatedType processed class.
+ */
+ @Override
+ public void initializeAfterBeanDiscovery(EnhancedAnnotatedType<T> annotatedType) {
+ initializeInterceptionModel(annotatedType);
+
+ InterceptionModel interceptionModel = null;
+ if (isInterceptionCandidate()) {
+ interceptionModel = beanManager.getInterceptorModelRegistry().get(getType());
+ }
+ boolean hasNonConstructorInterceptors = interceptionModel != null
+ && (interceptionModel.hasExternalNonConstructorInterceptors()
+ || interceptionModel.hasTargetClassInterceptors());
+
+ List<Decorator<?>> decorators = null;
+ if (getBean() != null && isInterceptionCandidate()) {
+ decorators = beanManager.resolveDecorators(getBean().getTypes(), getBean().getQualifiers());
+ }
+ boolean hasDecorators = decorators != null && !decorators.isEmpty();
+ if (hasDecorators) {
+ checkDecoratedMethods(annotatedType, decorators);
+ }
+
+ if (hasNonConstructorInterceptors || hasDecorators) {
+ if (!(getInstantiator() instanceof DefaultInstantiator<?>)) {
+ throw new IllegalStateException("Unexpected instantiator " + getInstantiator());
+ }
+
+ /*
+ * Casting changed from DefaultInstantiator to a more abstract one because of using our custom JerseyInstantiator.
+ */
+ AbstractInstantiator<T> delegate = (AbstractInstantiator<T>) getInstantiator();
+ setInstantiator(
+ SubclassedComponentInstantiator.forInterceptedDecoratedBean(annotatedType, getBean(), delegate, beanManager));
+
+ if (hasDecorators) {
+ setInstantiator(new SubclassDecoratorApplyingInstantiator<>(
+ getBeanManager().getContextId(), getInstantiator(), getBean(), decorators));
+ }
+
+ if (hasNonConstructorInterceptors) {
+ setInstantiator(new InterceptorApplyingInstantiator<>(
+ getInstantiator(), interceptionModel, getType()));
+ }
+ }
+
+ if (isInterceptionCandidate()) {
+ setupConstructorInterceptionInstantiator(interceptionModel);
+ }
+ }
+
+ private void setupConstructorInterceptionInstantiator(InterceptionModel interceptionModel) {
+ if (interceptionModel != null && interceptionModel.hasExternalConstructorInterceptors()) {
+ setInstantiator(new ConstructorInterceptionInstantiator<>(getInstantiator(), interceptionModel, getType()));
+ }
+ }
+
+ private void checkNoArgsConstructor(EnhancedAnnotatedType<T> type) {
+ if (!beanManager.getServices().get(ProxyInstantiator.class).isUsingConstructor()) {
+ return;
+ }
+ EnhancedAnnotatedConstructor<T> constructor = type.getNoArgsEnhancedConstructor();
+ if (constructor == null) {
+ throw BeanLogger.LOG.decoratedHasNoNoargsConstructor(this);
+ } else if (constructor.isPrivate()) {
+ throw BeanLogger.LOG
+ .decoratedNoargsConstructorIsPrivate(this, Formats.formatAsStackTraceElement(constructor.getJavaMember()));
+ }
+ }
+
+ private void checkDecoratedMethods(EnhancedAnnotatedType<T> type, List<Decorator<?>> decorators) {
+ if (type.isFinal()) {
+ throw BeanLogger.LOG.finalBeanClassWithDecoratorsNotAllowed(this);
+ }
+ checkNoArgsConstructor(type);
+ for (Decorator<?> decorator : decorators) {
+ EnhancedAnnotatedType<?> decoratorClass;
+ if (decorator instanceof DecoratorImpl<?>) {
+ DecoratorImpl<?> decoratorBean = (DecoratorImpl<?>) decorator;
+ decoratorClass = decoratorBean.getBeanManager().getServices().get(ClassTransformer.class)
+ .getEnhancedAnnotatedType(decoratorBean.getAnnotated());
+ } else if (decorator instanceof CustomDecoratorWrapper<?>) {
+ decoratorClass = ((CustomDecoratorWrapper<?>) decorator).getEnhancedAnnotated();
+ } else {
+ throw BeanLogger.LOG.nonContainerDecorator(decorator);
+ }
+
+ for (EnhancedAnnotatedMethod<?, ?> decoratorMethod : decoratorClass.getEnhancedMethods()) {
+ EnhancedAnnotatedMethod<?, ?> method = type.getEnhancedMethod(decoratorMethod.getSignature());
+ if (method != null && !method.isStatic() && !method.isPrivate() && method.isFinal()) {
+ throw BeanLogger.LOG.finalBeanClassWithInterceptorsNotAllowed(this);
+ }
+ }
+ }
+ }
+
+ private void initializeInterceptionModel(EnhancedAnnotatedType<T> annotatedType) {
+ AbstractInstantiator<T> instantiator = (AbstractInstantiator<T>) getInstantiator();
+ if (instantiator.getConstructorInjectionPoint() == null) {
+ return; // this is a non-producible InjectionTarget (only created to inject existing instances)
+ }
+ if (isInterceptionCandidate() && !beanManager.getInterceptorModelRegistry().containsKey(getType())) {
+ buildInterceptionModel(annotatedType, instantiator);
+ }
+ }
+
+ private void buildInterceptionModel(EnhancedAnnotatedType<T> annotatedType, AbstractInstantiator<T> instantiator) {
+ new InterceptionModelInitializer<>(beanManager, annotatedType, annotatedType.getDeclaredEnhancedConstructor(
+ instantiator.getConstructorInjectionPoint().getSignature()), getBean()).init();
+ }
+
+ private boolean isInterceptor() {
+ return (getBean() instanceof Interceptor<?>) || getType().isAnnotationPresent(javax.interceptor.Interceptor.class);
+ }
+
+ private boolean isDecorator() {
+ return (getBean() instanceof Decorator<?>) || getType().isAnnotationPresent(javax.decorator.Decorator.class);
+ }
+
+ private boolean isInterceptionCandidate() {
+ return !isInterceptor() && !isDecorator() && !Modifier.isAbstract(getType().getJavaClass().getModifiers());
+ }
+
+ @Override
+ public T produce(CreationalContext<T> ctx) {
+ T instance;
+ if (delegate != null) {
+ instance = (T) delegate.produce(ctx);
+ } else {
+ instance = super.produce(ctx);
+ if (bean != null && !bean.getScope().equals(Dependent.class) && !getInstantiator().hasDecoratorSupport()) {
+ // This should be safe, but needs verification PLM
+ // Without this, the chaining of decorators will fail as the
+ // incomplete instance will be resolved
+ ctx.push(instance);
+ }
+ }
+ return instance;
+ }
+
+ public Instantiator<T> getInstantiator() {
+ return delegate != null ? delegate.getInstantiator() : super.getInstantiator();
+ }
+
+ public void setInstantiator(Instantiator<T> instantiator) {
+ if (this.delegate != null) {
+ delegate.setInstantiator(instantiator);
+ } else {
+ super.setInstantiator(instantiator);
+ }
+ }
+
+ @Override
+ public Bean<T> getBean() {
+ return this.bean;
+ }
+
+ /**
+ * In some cases Injection Resolvers cannot be provided during th creation of the object therefore must be set later on.
+ *
+ * @param resolvers all registered injection resolvers.
+ */
+ public void setInjectionResolvers(Collection<InjectionResolver> resolvers) {
+ this.resolvers = resolvers;
+ }
+
+ public EnhancedAnnotatedType<T> getEnhancedAnnotatedType() {
+ return enhancedAnnotatedType;
+ }
+
+ public JerseyTwofoldInstantiator<T> getTwofoldInstantiator() {
+ return (JerseyTwofoldInstantiator<T>) instantiator;
+ }
+}
diff --git a/incubator/cdi-inject-weld/src/main/java/org/glassfish/jersey/inject/weld/internal/injector/JerseyInstanceInjector.java b/incubator/cdi-inject-weld/src/main/java/org/glassfish/jersey/inject/weld/internal/injector/JerseyInstanceInjector.java
new file mode 100644
index 0000000..07cf0d3
--- /dev/null
+++ b/incubator/cdi-inject-weld/src/main/java/org/glassfish/jersey/inject/weld/internal/injector/JerseyInstanceInjector.java
@@ -0,0 +1,78 @@
+/*
+ * Copyright (c) 2021 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.inject.weld.internal.injector;
+
+import java.lang.reflect.Field;
+import java.util.Collection;
+import java.util.Map;
+import java.util.Set;
+
+import javax.enterprise.inject.spi.Bean;
+
+import org.glassfish.jersey.internal.inject.InjectionResolver;
+
+/**
+ * Class that accepts all registered {@link InjectionResolver} and inject all possible values annotated by JAX-RS annotations
+ * into provided instance in {@link #inject(Object)}.
+ *
+ * @author Petr Bouda
+ */
+class JerseyInstanceInjector<T> {
+
+ private final Bean<T> bean;
+ private final Map<Field, InjectionResolver> cachedFields;
+
+ private final JerseyProxyResolver proxyResolver = new JerseyProxyResolver();
+
+ /**
+ * Constructor that creates a new class injector for the given class.
+ *
+ * @param bean information about the injected class.
+ * @param resolvers all resolvers which are registered in the application.
+ */
+ JerseyInstanceInjector(Bean<T> bean, Collection<InjectionResolver> resolvers) {
+ this.bean = bean;
+ this.cachedFields = analyzeFields(bean.getBeanClass(), resolvers);
+ }
+
+ /**
+ * Takes an instance an inject the annotated field which were analyzed during the injector construction in method
+ * {@link #analyzeFields(Class, Collection)}.
+ *
+ * @param injectMe an instance into which the values will be injected.
+ */
+ void inject(T injectMe) {
+ InjectionUtils.justInject(injectMe, bean, cachedFields, proxyResolver);
+ }
+
+ /**
+ * Takes a class and returns all fields along with {@link InjectionResolver} which will be used for injection during injection
+ * process.
+ *
+ * @param clazz class to be analyzed.
+ * @param resolvers all registered injection resolvers.
+ * @return immutable map of all fields along with injection resolvers using that can be injected.
+ */
+ private Map<Field, InjectionResolver> analyzeFields(Class<?> clazz, Collection<InjectionResolver> resolvers) {
+ Map<? extends Class<?>, InjectionResolver> injectAnnotations = InjectionUtils.mapAnnotationToResolver(resolvers);
+
+ Collector collector = new Collector();
+ Set<Field> fields = InjectionUtils.getFields(clazz, injectAnnotations.keySet(), collector);
+ collector.throwIfErrors();
+ return InjectionUtils.mapElementToResolver(fields, injectAnnotations);
+ }
+}
diff --git a/incubator/cdi-inject-weld/src/main/java/org/glassfish/jersey/inject/weld/internal/injector/JerseyProxyResolver.java b/incubator/cdi-inject-weld/src/main/java/org/glassfish/jersey/inject/weld/internal/injector/JerseyProxyResolver.java
new file mode 100644
index 0000000..20c282c
--- /dev/null
+++ b/incubator/cdi-inject-weld/src/main/java/org/glassfish/jersey/inject/weld/internal/injector/JerseyProxyResolver.java
@@ -0,0 +1,195 @@
+/*
+ * Copyright (c) 2021 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.inject.weld.internal.injector;
+
+import java.lang.annotation.Annotation;
+import java.lang.reflect.AnnotatedElement;
+import java.lang.reflect.InvocationHandler;
+import java.lang.reflect.Method;
+import java.lang.reflect.ParameterizedType;
+import java.lang.reflect.Proxy;
+import java.lang.reflect.Type;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.function.Supplier;
+
+import javax.ws.rs.core.Application;
+
+import javax.enterprise.context.RequestScoped;
+
+import org.glassfish.jersey.internal.inject.Injectee;
+import org.glassfish.jersey.internal.inject.InjectionResolver;
+
+/**
+ * Class working with JAX-RS/Jersey types injected using {@link javax.ws.rs.core.Context} annotation and all other types which
+ * can be injected using using other {@code *Param} annotations.
+ * <p>
+ * Processed JAX-RS interfaces:
+ *
+ * @author Petr Bouda
+ * @see javax.ws.rs.core.UriInfo
+ * @see javax.ws.rs.core.Request
+ * @see javax.ws.rs.core.HttpHeaders
+ * @see javax.ws.rs.core.SecurityContext
+ * @see javax.ws.rs.core.Configuration
+ * @see javax.ws.rs.core.Application not proxiable because is registered as a singleton.
+ * @see javax.ws.rs.ext.Providers
+ */
+class JerseyProxyResolver {
+
+ /**
+ * Contains already created proxies for the given type.
+ * e.g. if the proxy has been already created for {@code UriInfo} don't create a new one and reuse the existing one.
+ */
+ private final ConcurrentHashMap<AnnotatedElement, Object> cachedProxies = new ConcurrentHashMap<>();
+
+ /**
+ * Classes in which is not needed to use a proxy because they are singletons.
+ */
+ private static final List<Class<?>> IGNORED_CLASSES = Collections.singletonList(Application.class);
+
+ /**
+ * Returns {@code true} if one of the proxiable annotations is present on the clazz into which values are injected.
+ * <p>
+ * In these cases the value is not proxiable:
+ * <ul>
+ * <li>Class without the annotation</li>
+ * <li>Class annotated by {@link javax.enterprise.context.RequestScoped}</li>
+ * <li>Class annotated by {@link org.glassfish.jersey.process.internal.RequestScoped}</li>
+ * <ul/>
+ *
+ * @param injectee information about the injection point.
+ * @return {@code true} if contains one proxiable annotation at least.
+ */
+ public boolean isProxiable(Injectee injectee) {
+ return !ignoredClass(injectee.getRequiredType()) && isProxiable(injectee.getParentClassScope());
+ }
+
+ /**
+ * Returns {@code true} if one of the proxiable annotations is present on the clazz.
+ * <p>
+ * In these cases the value is not proxiable:
+ * <ul>
+ * <li>Class without the annotation</li>
+ * <li>Class annotated by {@link javax.enterprise.context.RequestScoped}</li>
+ * <li>Class annotated by {@link org.glassfish.jersey.process.internal.RequestScoped}</li>
+ * <ul/>
+ *
+ * @param scopeAnnotation annotation belonging to the scope of the class.
+ * @return {@code true} if contains one proxiable annotation at least.
+ */
+ public boolean isProxiable(Class<? extends Annotation> scopeAnnotation) {
+ return ignoreProxy().stream().noneMatch(ignoredAnnotation -> ignoredAnnotation == scopeAnnotation);
+ }
+
+ /**
+ * Returns a proxy (newly created or cached) which is able to call {@link InjectionResolver} with the given {@link Injectee}
+ * to get the value in proper scope.
+ *
+ * @param injectee information about the injection point.
+ * @param resolver dedicated resolver which find the value.
+ * @return created proxy which resolve the value in the proper scope.
+ */
+ public Object proxy(Injectee injectee, InjectionResolver resolver) {
+ return cachedProxies.computeIfAbsent(injectee.getParent(), type -> createProxy(injectee, resolver));
+ }
+
+ /**
+ * Returns a proxy (newly created or cached) which is able to call the given {@link Supplier}. This method does not cache
+ * a result.
+ *
+ * @param injectee information about the injection point.
+ * @param supplier supplier called using the proxy.
+ * @return created proxy which resolve the value in the proper scope.
+ */
+ public Object noCachedProxy(Injectee injectee, Supplier<Object> supplier) {
+ return createProxy(getClass(injectee.getRequiredType()), supplier);
+ }
+
+ private Object createProxy(Injectee injectee, InjectionResolver resolver) {
+ return createProxy(getClass(injectee.getRequiredType()), () -> resolver.resolve(injectee));
+ }
+
+ private Object createProxy(Class<?> requiredClass, Supplier<Object> supplier) {
+ return Proxy.newProxyInstance(
+ requiredClass.getClassLoader(),
+ new Class<?>[] {requiredClass},
+ new JerseyInvocationHandler(supplier));
+ }
+
+ private Class<?> getClass(Type type) {
+ if (type instanceof ParameterizedType) {
+ ParameterizedType paramType = (ParameterizedType) type;
+ return (Class<?>) paramType.getRawType();
+ }
+
+ return (Class<?>) type;
+ }
+
+ /**
+ * Returns all annotations for which proxy will be created.
+ *
+ * @return all proxyable annotations.
+ */
+ private Collection<Class<? extends Annotation>> ignoreProxy() {
+ return Arrays.asList(RequestScoped.class, org.glassfish.jersey.process.internal.RequestScoped.class);
+ }
+
+ /**
+ * Classes in which is not needed to use a proxy because they are singletons.
+ *
+ * @return classes omitted during proxying.
+ */
+ private boolean ignoredClass(Type type) {
+ Class<?> clazz;
+ if (type instanceof ParameterizedType) {
+ ParameterizedType paramType = (ParameterizedType) type;
+ clazz = (Class<?>) paramType.getRawType();
+ } else {
+ clazz = (Class<?>) type;
+ }
+
+ return IGNORED_CLASSES.contains(clazz);
+ }
+
+ /**
+ * {@link InvocationHandler} to intercept a calling using a proxy by providing a value of the given injected type in a proper
+ * scope.
+ */
+ private static class JerseyInvocationHandler implements InvocationHandler {
+
+ private final Supplier<Object> supplier;
+
+ /**
+ * Creates a new invocation handler with supplier which provides a current injected value in proper scope.
+ *
+ * @param supplier provider of the value.
+ */
+ private JerseyInvocationHandler(Supplier<Object> supplier) {
+ this.supplier = supplier;
+ }
+
+ @Override
+ public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
+ Object target = supplier.get();
+ return method.invoke(target, args);
+ }
+ }
+}
diff --git a/incubator/cdi-inject-weld/src/main/java/org/glassfish/jersey/inject/weld/internal/injector/JerseyTwofoldInstantiator.java b/incubator/cdi-inject-weld/src/main/java/org/glassfish/jersey/inject/weld/internal/injector/JerseyTwofoldInstantiator.java
new file mode 100644
index 0000000..e9f6309
--- /dev/null
+++ b/incubator/cdi-inject-weld/src/main/java/org/glassfish/jersey/inject/weld/internal/injector/JerseyTwofoldInstantiator.java
@@ -0,0 +1,75 @@
+/*
+ * Copyright (c) 2021 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.inject.weld.internal.injector;
+
+import javax.enterprise.context.spi.CreationalContext;
+import org.jboss.weld.injection.ConstructorInjectionPoint;
+import org.jboss.weld.injection.producer.AbstractInstantiator;
+import org.jboss.weld.manager.BeanManagerImpl;
+
+import java.lang.reflect.Constructor;
+
+/**
+ * An implementation of an instantiator capable of instantiating different instance for the client and server side.
+ * @param <T> the class of the instantiator.
+ */
+public class JerseyTwofoldInstantiator<T> extends AbstractInstantiator<T> {
+
+ private final AbstractInstantiator<T> primaryInstantiator;
+ private ConstructorInjectionPoint<T> optionalConstructorInjectionPoint = null;
+
+ JerseyTwofoldInstantiator(AbstractInstantiator<T> serverInstantiator) {
+ this.primaryInstantiator = serverInstantiator;
+ }
+
+ @Override
+ public ConstructorInjectionPoint<T> getConstructorInjectionPoint() {
+ return primaryInstantiator.getConstructorInjectionPoint();
+ }
+
+ @Override
+ public boolean hasInterceptorSupport() {
+ return primaryInstantiator.hasDecoratorSupport();
+ }
+
+ @Override
+ public boolean hasDecoratorSupport() {
+ return primaryInstantiator.hasDecoratorSupport();
+ }
+
+ @Override
+ public Constructor<T> getConstructor() {
+ return primaryInstantiator.getConstructor();
+ }
+
+ @Override
+ public T newInstance(CreationalContext<T> ctx, BeanManagerImpl manager) {
+ final ConstructorInjectionPoint<T> cip =
+ optionalConstructorInjectionPoint == null || !JerseyClientCreationalContext.class.isInstance(ctx)
+ ? primaryInstantiator.getConstructorInjectionPoint()
+ : optionalConstructorInjectionPoint;
+ return cip.newInstance(manager, ctx);
+ }
+
+ /**
+ * Set the optional constuctor injection point for the client side instantiation.
+ * @param optionalConstructorInjectionPoint The optional constructor injection point.
+ */
+ public void setOptionalConstructorInjectionPoint(ConstructorInjectionPoint<T> optionalConstructorInjectionPoint) {
+ this.optionalConstructorInjectionPoint = optionalConstructorInjectionPoint;
+ }
+}
diff --git a/incubator/cdi-inject-weld/src/main/java/org/glassfish/jersey/inject/weld/internal/injector/MultiException.java b/incubator/cdi-inject-weld/src/main/java/org/glassfish/jersey/inject/weld/internal/injector/MultiException.java
new file mode 100644
index 0000000..2c7e31a
--- /dev/null
+++ b/incubator/cdi-inject-weld/src/main/java/org/glassfish/jersey/inject/weld/internal/injector/MultiException.java
@@ -0,0 +1,201 @@
+/*
+ * Copyright (c) 2021 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.inject.weld.internal.injector;
+
+import java.io.PrintStream;
+import java.io.PrintWriter;
+import java.util.LinkedList;
+import java.util.List;
+
+/**
+ * This exception can contain multiple other exceptions.
+ * However, it will also have the causal chain of the
+ * first exception added to the list of exceptions.
+ *
+ * @author John Wells (john.wells at oracle.com)
+ */
+public class MultiException extends RuntimeException {
+ /**
+ * For serialization
+ */
+ private static final long serialVersionUID = 2112432697858621044L;
+ private final Object lock = new byte[0]; // byte[0] is an arbitrary type that is Serializable
+ private final List<Throwable> throwables = new LinkedList<>();
+ private boolean reportToErrorService = true;
+
+ /**
+ * Creates an empty MultiException.
+ */
+ public MultiException() {
+ }
+
+ /**
+ * This list must have at least one element in it.
+ * The first element of the list will become the
+ * cause of this exception, and its message will become
+ * the message of this exception.
+ *
+ * @param ths A non-null, non-empty list of exceptions.
+ */
+ public MultiException(List<Throwable> ths) {
+ super(ths.get(0).getMessage(), ths.get(0));
+
+ for (Throwable th : ths) {
+ if (th instanceof MultiException) {
+ MultiException me = (MultiException) th;
+
+ throwables.addAll(me.throwables);
+ } else {
+ throwables.add(th);
+ }
+ }
+ }
+
+ /**
+ * This allows for construction of a MultiException
+ * with one element in its list.
+ *
+ * @param th May not be null.
+ */
+ public MultiException(Throwable th, boolean reportToErrorService) {
+ super(th.getMessage(), th);
+
+ if (th instanceof MultiException) {
+ MultiException me = (MultiException) th;
+
+ throwables.addAll(me.throwables);
+ } else {
+ throwables.add(th);
+ }
+
+ this.reportToErrorService = reportToErrorService;
+ }
+
+ /**
+ * This allows for construction of a MultiException
+ * with one element in its list.
+ *
+ * @param th May not be null.
+ */
+ public MultiException(Throwable th) {
+ this(th, true);
+ }
+
+ /**
+ * Gets all the errors associated with this MultiException.
+ *
+ * @return All the errors associated with this MultiException. Will
+ * not return null, but may return an empty object.
+ */
+ public List<Throwable> getErrors() {
+ synchronized (lock) {
+ return new LinkedList<>(throwables);
+ }
+ }
+
+ /**
+ * Adds an error to an existing exception.
+ *
+ * @param error The exception to add.
+ */
+ public void addError(Throwable error) {
+ synchronized (lock) {
+ throwables.add(error);
+ }
+ }
+
+ /**
+ * Gets the message associated with this exception.
+ */
+ public String getMessage() {
+ List<Throwable> listCopy = getErrors();
+ StringBuffer sb = new StringBuffer("A MultiException has " + listCopy.size() + " exceptions. They are:\n");
+
+ int lcv = 1;
+ for (Throwable th : listCopy) {
+ sb.append(lcv++ + ". " + th.getClass().getName() + ((th.getMessage() != null) ? ": " + th.getMessage() : "") + "\n");
+ }
+
+ return sb.toString();
+ }
+
+ /**
+ * Prints the stack trace of this exception to the given PrintStream.
+ */
+ public void printStackTrace(PrintStream s) {
+ List<Throwable> listCopy = getErrors();
+
+ if (listCopy.size() <= 0) {
+ super.printStackTrace(s);
+ return;
+ }
+
+ int lcv = 1;
+ for (Throwable th : listCopy) {
+ s.println("MultiException stack " + lcv++ + " of " + listCopy.size());
+ th.printStackTrace(s);
+ }
+ }
+
+ /**
+ * Prints the stack trace of this exception to the given PrintWriter.
+ */
+ public void printStackTrace(PrintWriter s) {
+ List<Throwable> listCopy = getErrors();
+
+ if (listCopy.size() <= 0) {
+ super.printStackTrace(s);
+ return;
+ }
+
+ int lcv = 1;
+ for (Throwable th : listCopy) {
+ s.println("MultiException stack " + lcv++ + " of " + listCopy.size());
+ th.printStackTrace(s);
+ }
+ }
+
+ /**
+ * Returns true if this exception should be reported
+ * to the error service when thrown during a creation
+ * or deletion of a service.
+ *
+ * @return true if this exception should be reported to
+ * the error service when creating or deleting a service.
+ */
+ public boolean getReportToErrorService() {
+ return reportToErrorService;
+ }
+
+ /**
+ * Sets if this exception should be reported
+ * to the error service when thrown during a creation
+ * or deletion of a service.
+ *
+ * @param report true if this exception should be reported to
+ * the error service when creating or deleting a service.
+ */
+ public void setReportToErrorService(boolean report) {
+ reportToErrorService = report;
+ }
+
+ @Override
+ public String toString() {
+ return getMessage();
+ }
+
+}
diff --git a/incubator/cdi-inject-weld/src/main/java/org/glassfish/jersey/inject/weld/internal/injector/NamedImpl.java b/incubator/cdi-inject-weld/src/main/java/org/glassfish/jersey/inject/weld/internal/injector/NamedImpl.java
new file mode 100644
index 0000000..6a7d5fb
--- /dev/null
+++ b/incubator/cdi-inject-weld/src/main/java/org/glassfish/jersey/inject/weld/internal/injector/NamedImpl.java
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 2021 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.inject.weld.internal.injector;
+
+import javax.inject.Named;
+
+import org.glassfish.jersey.internal.inject.AnnotationLiteral;
+
+/**
+ * This is an implementation of the {@link Named} annotation.
+ *
+ * @author John Wells (john.wells at oracle.com)
+ */
+class NamedImpl extends AnnotationLiteral<Named> implements Named {
+
+ /**
+ * For serialization
+ */
+ private static final long serialVersionUID = 9110325112008963155L;
+
+ private final String name;
+
+ /**
+ * Creates a {@link Named} annotation with the given name.
+ *
+ * @param name The non-null name to give the annotation.
+ */
+ NamedImpl(String name) {
+ this.name = name;
+ }
+
+ @Override
+ public String value() {
+ return name;
+ }
+
+ @Override
+ public String toString() {
+ return "@Named(" + name + ")";
+ }
+}
diff --git a/incubator/cdi-inject-weld/src/main/java/org/glassfish/jersey/inject/weld/internal/injector/ReflectionUtils.java b/incubator/cdi-inject-weld/src/main/java/org/glassfish/jersey/inject/weld/internal/injector/ReflectionUtils.java
new file mode 100644
index 0000000..e47a998
--- /dev/null
+++ b/incubator/cdi-inject-weld/src/main/java/org/glassfish/jersey/inject/weld/internal/injector/ReflectionUtils.java
@@ -0,0 +1,428 @@
+/*
+ * Copyright (c) 2021 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.inject.weld.internal.injector;
+
+import java.lang.reflect.AccessibleObject;
+import java.lang.reflect.Array;
+import java.lang.reflect.Field;
+import java.lang.reflect.GenericArrayType;
+import java.lang.reflect.ParameterizedType;
+import java.lang.reflect.Type;
+import java.lang.reflect.TypeVariable;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.LinkedHashSet;
+import java.util.Map;
+import java.util.Set;
+import java.util.logging.Logger;
+
+import org.glassfish.jersey.inject.weld.internal.type.GenericArrayTypeImpl;
+import org.glassfish.jersey.inject.weld.internal.type.ParameterizedTypeImpl;
+import org.glassfish.jersey.internal.util.collection.ImmutableCollectors;
+
+/**
+ * Utility class for getting the information from class using Reflection API.
+ *
+ * @author John Wells (john.wells at oracle.com)
+ * @author Petr Bouda
+ */
+class ReflectionUtils {
+
+ private static final Logger LOGGER = Logger.getLogger(ReflectionUtils.class.getName());
+
+ static Set<Field> getAllFields(Class<?> clazz) {
+ if (clazz == null || Object.class.equals(clazz)) {
+ return Collections.emptySet();
+ }
+ if (clazz.isInterface()) {
+ return Collections.emptySet();
+ }
+
+ Set<Field> retVal = new LinkedHashSet<>();
+ retVal.addAll(getDeclaredField(clazz));
+ retVal.addAll(getAllFields(clazz.getSuperclass()));
+ return retVal;
+ }
+
+ /**
+ * Gets the EXACT set of fields on this class only. No subclasses. So this set should be considered RAW and has not taken into
+ * account any subclasses.
+ *
+ * @param clazz The class to examine.
+ * @return all declared fields.
+ */
+ private static Set<Field> getDeclaredField(final Class<?> clazz) {
+ return Arrays.stream(secureGetDeclaredFields(clazz)).collect(ImmutableCollectors.toImmutableLinkedSet());
+ }
+
+ private static Field[] secureGetDeclaredFields(final Class<?> clazz) {
+ return AccessController.doPrivileged((PrivilegedAction<Field[]>) clazz::getDeclaredFields);
+ }
+
+ /**
+ * Resolves the generic type of a field given the actual class being instantiated
+ *
+ * @param topclass The instantiation class. Must not be null
+ * @param field The non-null field whose type to resolve
+ * @return The resolved field type by way of its subclasses. Will not return
+ * null, but may return the original fields generic type
+ */
+ static Type resolveField(Class<?> topclass, Field field) {
+ return resolveMember(topclass, field.getGenericType(), field.getDeclaringClass());
+ }
+
+ /**
+ * Resolves the generic type of a type and declaring class given the actual class being instantiated
+ *
+ * @param topclass The instantiation class. Must not be null
+ * @param lookingForType The type to resolve. Must not be null
+ * @param declaringClass The class of the entity declaring the lookingForType. Must not be null
+ * @return The resolved type by way of its subclasses. Will not return null but may
+ * return lookingForType if it could not be further resolved
+ */
+ private static Type resolveMember(Class<?> topclass, Type lookingForType, Class<?> declaringClass) {
+ Map<String, Type> typeArguments = typesFromSubClassToDeclaringClass(topclass, declaringClass);
+ if (typeArguments == null) {
+ return lookingForType;
+ }
+
+ if (lookingForType instanceof ParameterizedType) {
+ return fixTypeVariables((ParameterizedType) lookingForType, typeArguments);
+ }
+
+ if (lookingForType instanceof GenericArrayType) {
+ return fixGenericArrayTypeVariables((GenericArrayType) lookingForType, typeArguments);
+ }
+
+ if (!(lookingForType instanceof TypeVariable)) {
+ return lookingForType;
+ }
+
+ TypeVariable<?> tv = (TypeVariable<?>) lookingForType;
+ String typeVariableName = tv.getName();
+
+ Type retVal = typeArguments.get(typeVariableName);
+ if (retVal == null) {
+ return lookingForType;
+ }
+
+ if (retVal instanceof Class) {
+ return retVal;
+ }
+
+ if (retVal instanceof ParameterizedType) {
+ return fixTypeVariables((ParameterizedType) retVal, typeArguments);
+ }
+
+ if (retVal instanceof GenericArrayType) {
+ return fixGenericArrayTypeVariables((GenericArrayType) retVal, typeArguments);
+ }
+
+ return retVal;
+ }
+
+ private static Map<String, Type> typesFromSubClassToDeclaringClass(Class<?> topClass, Class<?> declaringClass) {
+ if (topClass.equals(declaringClass)) {
+ return null;
+ }
+
+ Type superType = topClass.getGenericSuperclass();
+ Class<?> superClass = getRawClass(superType);
+
+ while (superType != null && superClass != null) {
+ if (!(superType instanceof ParameterizedType)) {
+ // superType MUST be a Class in this case
+ if (superClass.equals(declaringClass)) {
+ return null;
+ }
+
+ superType = superClass.getGenericSuperclass();
+ superClass = getRawClass(superType);
+
+ continue;
+ }
+
+ ParameterizedType superPT = (ParameterizedType) superType;
+
+ Map<String, Type> typeArguments = getTypeArguments(superClass, superPT);
+
+ if (superClass.equals(declaringClass)) {
+ return typeArguments;
+ }
+
+ superType = superClass.getGenericSuperclass();
+ superClass = getRawClass(superType);
+
+ if (superType instanceof ParameterizedType) {
+ superType = fixTypeVariables((ParameterizedType) superType, typeArguments);
+ }
+ }
+
+ throw new AssertionError(topClass.getName() + " is not the same as or a subclass of " + declaringClass.getName());
+ }
+
+ /**
+ * Gets a mapping of type variable names of the raw class to type arguments of the parameterized type.
+ */
+ private static Map<String, Type> getTypeArguments(Class<?> rawClass, ParameterizedType type) {
+ Map<String, Type> typeMap = new HashMap<>();
+ Type[] typeArguments = type.getActualTypeArguments();
+
+ int i = 0;
+ for (TypeVariable<?> typeVariable : rawClass.getTypeParameters()) {
+ typeMap.put(typeVariable.getName(), typeArguments[i++]);
+ }
+ return typeMap;
+ }
+
+ /**
+ * Replace any TypeVariables in the given type's arguments with
+ * the actual argument types. Return the given type if no replacing
+ * is required.
+ */
+ private static Type fixTypeVariables(ParameterizedType type, Map<String, Type> typeArgumentsMap) {
+ Type[] newTypeArguments = getNewTypeArguments(type, typeArgumentsMap);
+ if (newTypeArguments != null) {
+ return new ParameterizedTypeImpl(type.getRawType(), newTypeArguments);
+ }
+ return type;
+ }
+
+ /**
+ * Get a new array of type arguments for the given ParameterizedType, replacing any TypeVariables with
+ * actual types. The types should be found in the given arguments map, keyed by variable name. Return
+ * null if no arguments needed to be replaced.
+ */
+ private static Type[] getNewTypeArguments(final ParameterizedType type,
+ final Map<String, Type> typeArgumentsMap) {
+
+ Type[] typeArguments = type.getActualTypeArguments();
+ Type[] newTypeArguments = new Type[typeArguments.length];
+ boolean newArgsNeeded = false;
+
+ int i = 0;
+ for (Type argType : typeArguments) {
+ if (argType instanceof TypeVariable) {
+ newTypeArguments[i] = typeArgumentsMap.get(((TypeVariable<?>) argType).getName());
+ newArgsNeeded = true;
+ } else if (argType instanceof ParameterizedType) {
+ ParameterizedType original = (ParameterizedType) argType;
+
+ Type[] internalTypeArgs = getNewTypeArguments(original, typeArgumentsMap);
+ if (internalTypeArgs != null) {
+ newTypeArguments[i] = new ParameterizedTypeImpl(original.getRawType(), internalTypeArgs);
+ newArgsNeeded = true;
+ } else {
+ newTypeArguments[i] = argType;
+ }
+ } else if (argType instanceof GenericArrayType) {
+ GenericArrayType gat = (GenericArrayType) argType;
+
+ Type internalTypeArg = getNewTypeArrayArguments(gat, typeArgumentsMap);
+ if (internalTypeArg != null) {
+ if (internalTypeArg instanceof Class<?>) {
+ newTypeArguments[i] = getArrayOfType((Class<?>) internalTypeArg);
+ newArgsNeeded = true;
+ } else if ((internalTypeArg instanceof ParameterizedType)
+ && (((ParameterizedType) internalTypeArg).getRawType() instanceof Class<?>)) {
+ ParameterizedType pt = (ParameterizedType) internalTypeArg;
+
+ newTypeArguments[i] = getArrayOfType((Class<?>) pt.getRawType());
+ newArgsNeeded = true;
+ } else {
+ newTypeArguments[i] = new GenericArrayTypeImpl(internalTypeArg);
+ newArgsNeeded = true;
+ }
+ } else {
+ newTypeArguments[i] = argType;
+ }
+ } else {
+ newTypeArguments[i] = argType;
+ }
+
+ i++;
+ }
+
+ return newArgsNeeded ? newTypeArguments : null;
+ }
+
+ /**
+ * Get a new Type for a GenericArrayType, replacing any TypeVariables with
+ * actual types. The types should be found in the given arguments map, keyed by variable name. Return
+ * null if no arguments needed to be replaced.
+ */
+ private static Type getNewTypeArrayArguments(final GenericArrayType gat,
+ final Map<String, Type> typeArgumentsMap) {
+
+ Type typeArgument = gat.getGenericComponentType();
+
+ if (typeArgument instanceof TypeVariable) {
+ return typeArgumentsMap.get(((TypeVariable<?>) typeArgument).getName());
+ }
+
+ if (typeArgument instanceof ParameterizedType) {
+ ParameterizedType original = (ParameterizedType) typeArgument;
+
+ Type[] internalTypeArgs = getNewTypeArguments(original, typeArgumentsMap);
+ if (internalTypeArgs != null) {
+ return new ParameterizedTypeImpl(original.getRawType(), internalTypeArgs);
+ }
+
+ return original;
+ }
+
+ if (typeArgument instanceof GenericArrayType) {
+ GenericArrayType original = (GenericArrayType) typeArgument;
+
+ Type internalTypeArg = getNewTypeArrayArguments(original, typeArgumentsMap);
+ if (internalTypeArg != null) {
+ if (internalTypeArg instanceof Class<?>) {
+ return getArrayOfType((Class<?>) internalTypeArg);
+ }
+
+ if (internalTypeArg instanceof ParameterizedType) {
+ ParameterizedType pt = (ParameterizedType) internalTypeArg;
+
+ if (pt.getRawType() instanceof Class<?>) {
+ return getArrayOfType((Class<?>) pt.getRawType());
+ }
+ }
+
+ return new GenericArrayTypeImpl(internalTypeArg);
+ }
+
+ return null;
+ }
+
+ return null;
+ }
+
+ /**
+ * Replace any TypeVariables in the given type's arguments with
+ * the actual argument types. Return the given type if no replacing
+ * is required.
+ */
+ private static Type fixGenericArrayTypeVariables(GenericArrayType type, Map<String, Type> typeArgumentsMap) {
+ Type newTypeArgument = getNewTypeArrayArguments(type, typeArgumentsMap);
+
+ if (newTypeArgument != null) {
+ if (newTypeArgument instanceof Class<?>) {
+ return getArrayOfType((Class<?>) newTypeArgument);
+ }
+
+ if (newTypeArgument instanceof ParameterizedType) {
+ ParameterizedType pt = (ParameterizedType) newTypeArgument;
+ if (pt.getRawType() instanceof Class<?>) {
+ return getArrayOfType((Class<?>) pt.getRawType());
+ }
+ }
+
+ return new GenericArrayTypeImpl(newTypeArgument);
+ }
+
+ return type;
+ }
+
+ private static Class<?> getArrayOfType(Class<?> type) {
+ return Array.newInstance(type, 0).getClass();
+ }
+
+ /**
+ * Given the type parameter gets the raw type represented
+ * by the type, or null if this has no associated raw class
+ *
+ * @param type The type to find the raw class on
+ * @return The raw class associated with this type
+ */
+ private static Class<?> getRawClass(Type type) {
+ if (type == null) {
+ return null;
+ }
+
+ if (type instanceof GenericArrayType) {
+ Type componentType = ((GenericArrayType) type).getGenericComponentType();
+
+ if (!(componentType instanceof ParameterizedType) && !(componentType instanceof Class)) {
+ // type variable is not supported
+ return null;
+ }
+
+ Class<?> rawComponentClass = getRawClass(componentType);
+
+ String forNameName = "[L" + rawComponentClass.getName() + ";";
+ try {
+ return Class.forName(forNameName);
+ } catch (Throwable th) {
+ // ignore, but return null
+ return null;
+ }
+ }
+
+ if (type instanceof Class) {
+ return (Class<?>) type;
+ }
+
+ if (type instanceof ParameterizedType) {
+ Type rawType = ((ParameterizedType) type).getRawType();
+ if (rawType instanceof Class) {
+ return (Class<?>) rawType;
+ }
+ }
+
+ return null;
+ }
+
+ /**
+ * Sets the given field to the given value
+ *
+ * @param field The non-null field to set
+ * @param instance The non-null instance to set into
+ * @param value The value to which the field should be set
+ * @throws Throwable If there was some exception while setting the field
+ */
+ static void setField(Field field, Object instance, Object value) throws Throwable {
+ setAccessible(field);
+
+ try {
+ field.set(instance, value);
+ } catch (IllegalArgumentException | IllegalAccessException ex) {
+ LOGGER.warning(String.format("Failed during setting a value into Class: %s, Field: %s",
+ field.getDeclaringClass().getName(), field.getName()));
+ throw ex;
+ }
+ }
+
+ /**
+ * Sets this accessible object to be accessible using the permissions of
+ * the hk2-locator bundle (which will need the required grant)
+ *
+ * @param ao The object to change
+ */
+ private static void setAccessible(final AccessibleObject ao) {
+ if (ao.isAccessible()) {
+ return;
+ }
+
+ AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
+ ao.setAccessible(true);
+ return null;
+ });
+ }
+}
diff --git a/incubator/cdi-inject-weld/src/main/java/org/glassfish/jersey/inject/weld/internal/injector/WrappingJerseyInjectionTarget.java b/incubator/cdi-inject-weld/src/main/java/org/glassfish/jersey/inject/weld/internal/injector/WrappingJerseyInjectionTarget.java
new file mode 100644
index 0000000..48a3ded
--- /dev/null
+++ b/incubator/cdi-inject-weld/src/main/java/org/glassfish/jersey/inject/weld/internal/injector/WrappingJerseyInjectionTarget.java
@@ -0,0 +1,130 @@
+/*
+ * Copyright (c) 2021 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.inject.weld.internal.injector;
+
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Set;
+
+import javax.enterprise.context.spi.CreationalContext;
+import javax.enterprise.inject.InjectionException;
+import javax.enterprise.inject.spi.Bean;
+import javax.enterprise.inject.spi.InjectionPoint;
+import javax.enterprise.inject.spi.InjectionTarget;
+
+import org.glassfish.jersey.internal.inject.InjectionResolver;
+import org.glassfish.jersey.internal.util.collection.LazyValue;
+import org.glassfish.jersey.internal.util.collection.Value;
+import org.glassfish.jersey.internal.util.collection.Values;
+
+/**
+ * An implementation of {@link InjectionTarget} that just wraps the provided {@code InjectionTarget} because of additional
+ * features in an injection phase.
+ *
+ * @author Petr Bouda
+ */
+public class WrappingJerseyInjectionTarget<T> extends AbstractInjectionTarget<T> {
+
+ private static InjectionTarget NOOP_INJECTION_TARGET = new NoOpInjectionTarget();
+
+ private final Bean<T> bean;
+ private final LazyValue<JerseyInstanceInjector<T>> injector;
+ private final InjectionTarget<T> delegate;
+ private Collection<InjectionResolver> resolvers;
+
+ /**
+ * Creates a new jersey injection target with delegate as a {@link NoOpInjectionTarget} that creates no operation that
+ * means that only jersey injection is available as a additional feature.
+ *
+ * @param bean bean as descriptor of the class which will be injected.
+ * @param resolvers all resolvers that can provide a valued for Jersey-specific injection.
+ */
+ public WrappingJerseyInjectionTarget(Bean<T> bean, Collection<InjectionResolver> resolvers) {
+ this(NOOP_INJECTION_TARGET, bean, resolvers);
+ }
+
+ /**
+ * An implementation of {@link InjectionTarget} for classes that do not fulfill bean class requirements
+ * (e.g. are abstract or non-static inner classes). Instances of these class can be injected using this implementation. If the
+ * application attempts to {@link #produce(CreationalContext)} a new instance of the class, {@code CreationException} is
+ * thrown.
+ *
+ * @param delegate CDI specific injection target.
+ * @param bean bean as descriptor of the class which will be injected.
+ * @param resolvers all resolvers that can provide a valued for Jersey-specific injection.
+ */
+ public WrappingJerseyInjectionTarget(InjectionTarget<T> delegate, Bean<T> bean, Collection<InjectionResolver> resolvers) {
+ this.bean = bean;
+ this.delegate = delegate;
+ this.resolvers = resolvers;
+ this.injector = Values.lazy((Value<JerseyInstanceInjector<T>>)
+ () -> new JerseyInstanceInjector<>(bean, this.resolvers));
+ }
+
+ @Override
+ public void inject(T instance, CreationalContext<T> ctx) {
+ /*
+ * If an instance contains any fields which be injected by Jersey then Jersey attempts to inject them using annotations
+ * retrieves from registered InjectionResolvers.
+ */
+ try {
+ injector.get().inject(instance);
+ } catch (Throwable cause) {
+ throw new InjectionException(
+ "Exception occurred during Jersey/JAX-RS annotations processing in the class: " + bean.getBeanClass(), cause);
+ }
+
+ /*
+ * The rest of the fields (annotated by @Inject) are injected using CDI.
+ */
+ super.inject(instance, ctx);
+ }
+
+ @Override
+ InjectionTarget<T> delegate() {
+ return delegate;
+ }
+
+ private static class NoOpInjectionTarget implements InjectionTarget<Object> {
+
+ @Override
+ public void inject(Object instance, CreationalContext<Object> ctx) {
+ }
+
+ @Override
+ public void postConstruct(Object instance) {
+ }
+
+ @Override
+ public void preDestroy(Object instance) {
+ }
+
+ @Override
+ public Object produce(CreationalContext<Object> ctx) {
+ return null;
+ }
+
+ @Override
+ public void dispose(Object instance) {
+ }
+
+ @Override
+ public Set<InjectionPoint> getInjectionPoints() {
+ return Collections.emptySet();
+ }
+ }
+}
diff --git a/incubator/cdi-inject-weld/src/main/java/org/glassfish/jersey/inject/weld/internal/managed/BinderRegisterExtension.java b/incubator/cdi-inject-weld/src/main/java/org/glassfish/jersey/inject/weld/internal/managed/BinderRegisterExtension.java
new file mode 100644
index 0000000..da291df
--- /dev/null
+++ b/incubator/cdi-inject-weld/src/main/java/org/glassfish/jersey/inject/weld/internal/managed/BinderRegisterExtension.java
@@ -0,0 +1,912 @@
+/*
+ * Copyright (c) 2021 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.inject.weld.internal.managed;
+
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Constructor;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Type;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.function.Supplier;
+import java.util.stream.Collectors;
+
+import javax.annotation.Priority;
+import javax.enterprise.context.ApplicationScoped;
+import javax.enterprise.context.Dependent;
+import javax.enterprise.context.NormalScope;
+import javax.enterprise.context.SessionScoped;
+import javax.enterprise.inject.spi.AnnotatedType;
+import javax.enterprise.inject.spi.BeforeBeanDiscovery;
+import javax.enterprise.inject.spi.ProcessAnnotatedType;
+import javax.enterprise.inject.spi.Unmanaged;
+import javax.enterprise.inject.spi.WithAnnotations;
+import javax.inject.Scope;
+import javax.inject.Singleton;
+
+import javax.enterprise.event.Observes;
+import javax.enterprise.inject.spi.AfterBeanDiscovery;
+import javax.enterprise.inject.spi.BeanManager;
+import javax.enterprise.inject.spi.Extension;
+import javax.enterprise.inject.spi.ProcessInjectionTarget;
+
+import javax.ws.rs.Path;
+import javax.ws.rs.RuntimeType;
+import javax.ws.rs.container.DynamicFeature;
+import javax.ws.rs.core.Feature;
+import javax.ws.rs.core.GenericType;
+import javax.ws.rs.core.MultivaluedHashMap;
+import javax.ws.rs.core.MultivaluedMap;
+import javax.ws.rs.core.Application;
+import javax.ws.rs.ext.Provider;
+
+import org.glassfish.jersey.inject.weld.internal.data.BindingBeanPair;
+import org.glassfish.jersey.inject.weld.internal.inject.InitializableSupplierInstanceBinding;
+import org.glassfish.jersey.inject.weld.internal.scope.RequestScopeBean;
+import org.glassfish.jersey.inject.weld.internal.inject.InitializableInstanceBinding;
+import org.glassfish.jersey.inject.weld.internal.bean.BeanHelper;
+import org.glassfish.jersey.inject.weld.internal.injector.ContextInjectionResolverImpl;
+import org.glassfish.jersey.inject.weld.internal.injector.JerseyInjectionTarget;
+import org.glassfish.jersey.inject.weld.internal.scope.CdiRequestScope;
+import org.glassfish.jersey.inject.weld.spi.BootstrapPreinitialization;
+import org.glassfish.jersey.internal.BootstrapBag;
+import org.glassfish.jersey.internal.ServiceFinder;
+import org.glassfish.jersey.internal.inject.AbstractBinder;
+import org.glassfish.jersey.internal.inject.Binder;
+import org.glassfish.jersey.internal.inject.Binding;
+import org.glassfish.jersey.internal.inject.Bindings;
+import org.glassfish.jersey.internal.inject.ClassBinding;
+import org.glassfish.jersey.internal.inject.CustomAnnotationLiteral;
+import org.glassfish.jersey.internal.inject.ForeignDescriptor;
+import org.glassfish.jersey.internal.inject.InjectionManager;
+import org.glassfish.jersey.internal.inject.InjectionResolver;
+import org.glassfish.jersey.internal.inject.InjectionResolverBinding;
+import org.glassfish.jersey.internal.inject.InstanceBinding;
+import org.glassfish.jersey.internal.inject.Providers;
+import org.glassfish.jersey.internal.inject.ServiceHolder;
+import org.glassfish.jersey.internal.inject.SupplierClassBinding;
+import org.glassfish.jersey.internal.inject.SupplierInstanceBinding;
+
+import org.glassfish.jersey.internal.util.collection.Ref;
+import org.glassfish.jersey.internal.util.collection.Refs;
+import org.glassfish.jersey.process.internal.RequestScope;
+import org.glassfish.jersey.process.internal.RequestScoped;
+import org.glassfish.jersey.server.ApplicationHandler;
+import org.glassfish.jersey.server.ResourceConfig;
+import org.jboss.weld.injection.producer.BasicInjectionTarget;
+import org.jboss.weld.injection.producer.BeanInjectionTarget;
+
+/**
+ * CDI extension that handles CDI bootstrap events and registers Jersey's internally used components and components registered
+ * using {@link Application}.
+ */
+class BinderRegisterExtension implements Extension {
+
+ private AtomicBoolean registrationDone = new AtomicBoolean(false);
+ private Supplier<BeanManager> beanManagerSupplier;
+ private Ref<InjectionManager> serverInjectionManager = Refs.emptyRef();
+
+ private BootstrapInjectionManager clientBootstrapInjectionManager = new BootstrapInjectionManager(RuntimeType.CLIENT);
+ private WrappingInjectionManager serverBootstrapInjectionManager = new WrappingInjectionManager()
+ .setInjectionManager(new BootstrapInjectionManager(RuntimeType.SERVER));
+ private BootstrapBag bootstrapBag = new BootstrapBag();
+
+ private final CachingBinder clientBindings = new CachingBinder(serverInjectionManager);
+ private final CachingBinder serverBindings = new CachingBinder(serverInjectionManager) {
+ @Override
+ protected void configure() {
+ install(new ContextInjectionResolverImpl.Binder(beanManagerSupplier));
+ bind(InitializableInstanceBinding.from(Bindings.service(serverInjectionManager.get()).to(InjectionManager.class)));
+ }
+ };
+ private final CachingBinder annotatedBeansBinder = new CachingBinder(serverInjectionManager);
+ private final MergedBindings mergedBindings = new MergedBindings(serverBindings, clientBindings);
+
+ private final List<InitializableInstanceBinding> initializableInstanceBindings = new LinkedList<>();
+ private final List<InitializableSupplierInstanceBinding> initializableSupplierInstanceBindings = new LinkedList<>();
+ private final MultivaluedMap<Type, BindingBeanPair> supplierClassBindings = new MultivaluedHashMap<>();
+ private final MultivaluedMap<Type, BindingBeanPair> classBindings = new MultivaluedHashMap<>();
+ private final List<JerseyInjectionTarget> jerseyInjectionTargets = new LinkedList<>();
+ private final List<InjectionResolver> injectionResolvers = new LinkedList<>();
+ private final Map<Class<?>, Class<? extends Annotation>> annotatedBeans = new HashMap<>();
+ private final List<Class<Application>> applications = new LinkedList<>();
+ final Set<Class<?>> managedBeans = new HashSet<>();
+
+ /**
+ * Ignores the classes which are manually added using bindings (through {@link Application} class) and scanned by CDI.
+ * The manual adding is privileged and the beans scanned using CDI are ignored.
+ * <p>
+ * TODO: The method counts with the condition that the all bindings are known before the CDI scanning has been started,
+ * can be changed during the migration from CDI SE to JAVA EE environment.
+ *
+ * @param pat processed type.
+ * @param <T> type of the scanned bean.
+ */
+ <T> void ignoreManuallyRegisteredComponents(
+ @Observes @WithAnnotations({ Path.class, Provider.class }) ProcessAnnotatedType<T> pat) {
+ final AnnotatedType<T> annotatedType = pat.getAnnotatedType();
+ for (Binding binding : mergedBindings.getBindings()) {
+ if (ClassBinding.class.isAssignableFrom(binding.getClass())) {
+ ClassBinding<?> classBinding = (ClassBinding<?>) binding;
+ if (annotatedType.getJavaClass() == classBinding.getService()) {
+ pat.veto();
+ return;
+ }
+ } else if (InstanceBinding.class.isAssignableFrom(binding.getClass())) {
+ InstanceBinding<?> instanceBinding = (InstanceBinding<?>) binding;
+ if (annotatedType.getJavaClass() == instanceBinding.getService().getClass()) {
+ pat.veto();
+ return;
+ }
+ }
+ }
+ if (annotatedType.isAnnotationPresent(Path.class)) {
+ boolean hasScope = false;
+ for (Annotation annotation : annotatedType.getAnnotations()) {
+ if (annotation.annotationType().isAnnotationPresent(Scope.class)
+ || annotation.annotationType().isAnnotationPresent(NormalScope.class)) {
+ hasScope = true;
+ break;
+ }
+ }
+ if (!hasScope) {
+ annotatedBeans.put(annotatedType.getJavaClass(), javax.enterprise.context.RequestScoped.class);
+ pat.configureAnnotatedType().add(javax.enterprise.context.RequestScoped.Literal.INSTANCE);
+ }
+ }
+
+
+ }
+
+ <T> void registerJerseyRequestScopedResources(
+ @Observes @WithAnnotations(RequestScoped.class) ProcessAnnotatedType<T> pat) {
+ if (pat.getAnnotatedType().isAnnotationPresent(RequestScoped.class)
+ && !pat.getAnnotatedType().isAnnotationPresent(javax.enterprise.context.RequestScoped.class)) {
+ pat.configureAnnotatedType().remove(a -> RequestScoped.class.isInstance(a))
+ .add(javax.enterprise.context.RequestScoped.Literal.INSTANCE);
+ annotatedBeans.put(pat.getAnnotatedType().getJavaClass(), javax.enterprise.context.RequestScoped.class);
+ }
+ }
+
+ void processRegistrars(@Observes BeforeBeanDiscovery beforeBeanDiscovery, BeanManager beanManager) {
+ CdiInjectionManagerFactoryBase.setBeanManager(beanManager);
+ processRegistrars();
+ }
+
+ void handleRequestScoped(
+ @Observes @WithAnnotations({javax.enterprise.context.RequestScoped.class}) ProcessAnnotatedType<?> pat) {
+ final Class<?> javaClass = pat.getAnnotatedType().getJavaClass();
+ if (isJaxrs(javaClass) && isNotJerseyInternal(javaClass)) {
+ pat.configureAnnotatedType().add(CustomAnnotationLiteral.INSTANCE);
+ annotatedBeans.put(javaClass, javax.enterprise.context.RequestScoped.class);
+ }
+ }
+
+ <T> void handleApplicationScoped(
+ @Observes @WithAnnotations({ApplicationScoped.class}) ProcessAnnotatedType<T> pat) {
+ final Class<T> javaClass = pat.getAnnotatedType().getJavaClass();
+ if (Application.class.isAssignableFrom(javaClass)) {
+ pat.veto();
+ applications.add((Class<Application>) javaClass);
+ } else if (isJaxrs(javaClass) && isNotJerseyInternal(javaClass)) {
+ pat.configureAnnotatedType().add(CustomAnnotationLiteral.INSTANCE);
+ annotatedBeans.put(javaClass, ApplicationScoped.class);
+ }
+ }
+
+ void handleDependent(@Observes @WithAnnotations({Dependent.class}) ProcessAnnotatedType<?> pat) {
+ final Class<?> javaClass = pat.getAnnotatedType().getJavaClass();
+ if (isJaxrs(javaClass) && isNotJerseyInternal(javaClass)) {
+ pat.configureAnnotatedType().add(CustomAnnotationLiteral.INSTANCE);
+ annotatedBeans.put(javaClass, Dependent.class);
+ }
+ }
+
+ void handleSessionScoped(@Observes @WithAnnotations({SessionScoped.class}) ProcessAnnotatedType<?> pat) {
+ final Class<?> javaClass = pat.getAnnotatedType().getJavaClass();
+ if (isJaxrs(javaClass) && isNotJerseyInternal(javaClass)) {
+ pat.configureAnnotatedType().add(CustomAnnotationLiteral.INSTANCE);
+ annotatedBeans.put(javaClass, SessionScoped.class);
+ }
+ }
+
+ void registerSingletonSubResources(@Observes @WithAnnotations({Singleton.class}) ProcessAnnotatedType<?> pat){
+ final Class<?> resourceClass = pat.getAnnotatedType().getJavaClass();
+ if (resourceClass.getAnnotation(Path.class) != null) {
+ annotatedBeans.put(resourceClass, Singleton.class);
+ } else if (BeanHelper.isResourceClass(resourceClass)) {
+ annotatedBeans.put(resourceClass, Singleton.class);
+ }
+ }
+
+ void registerJerseyProviders(@Observes @WithAnnotations({Priority.class}) ProcessAnnotatedType<?> pat) {
+ final Class<?> javaClass = pat.getAnnotatedType().getJavaClass();
+ if (!isNotJerseyInternal(javaClass)) {
+ pat.veto(); //veto Jersey internal
+ }
+ annotatedBeans.put(javaClass, Priority.class);
+ }
+
+ /**
+ * Wraps all JAX-RS components by Jersey-specific injection target.
+ *
+ * @param pit process injection target.
+ * @param <T> type of the processed injection target.
+ */
+ public <T> void observeInjectionTarget(@Observes ProcessInjectionTarget<T> pit) {
+ if (!BeanInjectionTarget.class.isInstance(pit.getInjectionTarget())) {
+ return;
+ }
+ BasicInjectionTarget<T> it = (BasicInjectionTarget<T>) pit.getInjectionTarget();
+ JerseyInjectionTarget<T> jerseyInjectionTarget =
+ new JerseyInjectionTarget<>(it, pit.getAnnotatedType().getJavaClass());
+ jerseyInjectionTargets.add(jerseyInjectionTarget);
+ pit.setInjectionTarget(jerseyInjectionTarget);
+ }
+
+ /**
+ * Takes all registered bindings and registers them in {@link BeanManager}.
+ * <p>
+ * Method should register only Jersey internal components and class/instances registered using {@link Application}. Registered
+ * classes/instances have priority therefore CDI scanning should veto these classes/instances during {
+ *
+ * @param abd {@code AfterBeanDiscovery} event.
+ * @param beanManager current {@code BeanManager}.
+ * @link ProcessAnnotatedType} bootstrap phase.
+ */
+ void registerBeans(@Observes AfterBeanDiscovery abd, BeanManager beanManager) {
+ serverInjectionManager.set(new CdiInjectionManager(beanManager, mergedBindings));
+
+ beanManagerSupplier = () -> beanManager; // set bean manager supplier to be called by bindings#configure
+ CdiInjectionManagerFactoryBase.setBeanManager(beanManager);
+
+ registerApplicationHandler(beanManager);
+
+ registrationDone.set(true); //
+
+ final List<InjectionResolver> contextInjectionResolvers = serverBindings.getBindings().stream()
+ .filter(binding -> InjectionResolverBinding.class.isAssignableFrom(binding.getClass()))
+ .map(InjectionResolverBinding.class::cast)
+ .map(InjectionResolverBinding::getResolver)
+ .collect(Collectors.toList());
+
+ injectionResolvers.addAll(contextInjectionResolvers);
+
+ /*
+ * Provide registered InjectionResolvers to Jersey's components which has been discovered by CDI in
+ * ProcessInjectionTarget bootstrap phase.
+ */
+ jerseyInjectionTargets.forEach(injectionTarget -> injectionTarget.setInjectionResolvers(injectionResolvers));
+
+ registerBeans(RuntimeType.SERVER, this.serverBindings, abd, beanManager);
+ registerBeans(RuntimeType.CLIENT, this.clientBindings, abd, beanManager);
+
+ abd.addBean(new RequestScopeBean(beanManager));
+
+ addAnnotatedBeans(abd, beanManager);
+
+ serverBootstrapInjectionManager.setInjectionManager(serverInjectionManager.get());
+ ((CdiInjectionManager) serverInjectionManager.get()).managedBeans = managedBeans;
+ }
+
+ private void registerBeans(RuntimeType runtimeType, CachingBinder binder, AfterBeanDiscovery abd,
+ BeanManager beanManager) {
+ final Collection<Binding> bindings = binder.getBindings();
+ binder.setReadOnly();
+
+ allBindingsLabel:
+ for (Binding binding : bindings) {
+ if (ClassBinding.class.isAssignableFrom(binding.getClass())) {
+ if (RuntimeType.CLIENT == runtimeType) {
+ for (Type contract : ((ClassBinding<?>) binding).getContracts()) {
+ final List<BindingBeanPair> preregistered = classBindings.get(contract);
+ if (preregistered != null && preregistered.size() == 1) {
+ BeanHelper.updateBean(
+ (ClassBinding<?>) binding, preregistered.get(0), injectionResolvers, beanManager);
+ continue allBindingsLabel;
+ }
+ }
+ }
+ BindingBeanPair pair = BeanHelper.registerBean(
+ runtimeType, (ClassBinding<?>) binding, abd, injectionResolvers, beanManager);
+ for (Type contract : ((ClassBinding<?>) binding).getContracts()) {
+ classBindings.add(contract, pair);
+ }
+ } else if (SupplierClassBinding.class.isAssignableFrom(binding.getClass())) {
+ if (RuntimeType.CLIENT == runtimeType) {
+ for (Type contract : ((SupplierClassBinding<?>) binding).getContracts()) {
+ final List<BindingBeanPair> preregistered = supplierClassBindings.get(contract);
+ if (preregistered != null && preregistered.size() == 1) {
+ BeanHelper.updateSupplierBean(
+ (SupplierClassBinding<?>) binding, preregistered.get(0), injectionResolvers, beanManager);
+ continue allBindingsLabel;
+ }
+ }
+ }
+ BindingBeanPair pair = BeanHelper.registerSupplier(
+ runtimeType, (SupplierClassBinding<?>) binding, abd, injectionResolvers, beanManager);
+ for (Type contract : ((SupplierClassBinding<?>) binding).getContracts()) {
+ supplierClassBindings.add(contract, pair);
+ }
+ } else if (InitializableInstanceBinding.class.isAssignableFrom(binding.getClass())) {
+ if (RuntimeType.SERVER == runtimeType
+ || !matchInitializableInstanceBinding((InitializableInstanceBinding<?>) binding)) {
+ initializableInstanceBindings.add((InitializableInstanceBinding<?>) binding);
+ BeanHelper.registerBean(
+ runtimeType, (InitializableInstanceBinding<?>) binding, abd, injectionResolvers, beanManager);
+ }
+ } else if (InitializableSupplierInstanceBinding.class.isInstance(binding)) {
+ if (RuntimeType.SERVER == runtimeType
+ || !matchInitializableSupplierInstanceBinding((InitializableSupplierInstanceBinding) binding)) {
+ initializableSupplierInstanceBindings.add((InitializableSupplierInstanceBinding) binding);
+ BeanHelper.registerSupplier(runtimeType, (InitializableSupplierInstanceBinding<?>) binding, abd, beanManager);
+ }
+ }
+ }
+ }
+
+ private void addAnnotatedBeans(AfterBeanDiscovery abd, BeanManager beanManager) {
+ for (Map.Entry<Class<?>, Class<? extends Annotation>> contract : annotatedBeans.entrySet()) {
+ for (Binding binding : serverBindings.getBindings()) {
+ if (ClassBinding.class.isInstance(binding)) {
+ if (((ClassBinding) binding).getService() == contract.getClass()) {
+ break;
+ }
+ }
+ if (InitializableInstanceBinding.class.isInstance(binding)) {
+ if (((InitializableInstanceBinding) binding).getImplementationType() == contract.getClass()) {
+ break;
+ }
+ }
+ }
+ if (isNotJerseyInternal(contract.getKey())) {
+ if (beanManager.getBeans(contract.getKey()).isEmpty()) {
+ final ClassBinding<?> binding = bind(contract.getKey(), annotatedBeansBinder);
+ if (Singleton.class.equals(contract.getValue())) {
+ binding.in(Singleton.class);
+ }
+ }
+ managedBeans.add(contract.getKey()); // add either way
+ }
+ }
+
+ registerBeans(RuntimeType.SERVER, annotatedBeansBinder, abd, beanManager);
+ serverBindings.getBindings().addAll(annotatedBeansBinder.getBindings());
+ }
+
+ private void registerApplicationHandler(BeanManager beanManager) {
+ final ResourceConfig resourceConfig = new ResourceConfig();
+
+ for (Class<Application> applicationClass : applications) {
+ bindApplication(applicationClass, resourceConfig, beanManager);
+ }
+
+ new ApplicationHandler(resourceConfig);
+ }
+
+ private void bindApplication(Class<Application> applicationClass, ResourceConfig resourceConfig, BeanManager beanManager) {
+ final Application application = new Unmanaged<>(applicationClass).newInstance().produce().get();
+
+ for (Class<?> clazz : application.getClasses()) {
+ if (beanManager.getBeans(clazz).isEmpty()) {
+ // prevent double registration of a class
+ // bind(clazz, binder);
+ resourceConfig.register(clazz);
+ } else if (!annotatedBeans.containsKey(clazz)) {
+ annotatedBeans.put(clazz, Provider.class);
+ }
+ }
+ for (Object singleton : application.getSingletons()) {
+ final Class<?> clazz = singleton.getClass();
+ if (beanManager.getBeans(clazz).isEmpty()) {
+ // prevent double registration of a class
+// final InstanceBinding<?> binding = binder.bind(singleton);
+// toSuper(clazz, binding);
+ resourceConfig.register(singleton);
+ } else if (!annotatedBeans.containsKey(clazz)) {
+ annotatedBeans.put(clazz, Provider.class);
+ }
+ }
+ }
+
+// private void bindApplication(Class<Application> applicationClass, AbstractBinder binder, BeanManager beanManager) {
+// final Application application = new Unmanaged<>(applicationClass).newInstance().produce().get();
+// final CommonConfig commonConfig = new CommonConfig(RuntimeType.SERVER, ComponentBag.INCLUDE_ALL);
+//
+// for (Class<?> clazz : application.getClasses()) {
+// if (beanManager.getBeans(clazz).isEmpty()) {
+// // prevent double registration of a class
+// // bind(clazz, binder);
+// commonConfig.register(clazz);
+// } else if (!annotatedBeans.containsKey(clazz)) {
+// annotatedBeans.put(clazz, Provider.class);
+// }
+// }
+// for (Object singleton : application.getSingletons()) {
+// final Class<?> clazz = singleton.getClass();
+// if (beanManager.getBeans(clazz).isEmpty()) {
+// // prevent double registration of a class
+//// final InstanceBinding<?> binding = binder.bind(singleton);
+//// toSuper(clazz, binding);
+// commonConfig.register(singleton);
+// } else if (!annotatedBeans.containsKey(clazz)) {
+// annotatedBeans.put(clazz, Provider.class);
+// }
+// }
+// }
+
+ private static <T> ClassBinding<T> bind(Class<T> clazz, AbstractBinder binder) {
+ final ClassBinding<T> binding = binder.bindAsContract(clazz);
+ return toSuper(clazz, binding);
+ }
+
+ private static <T extends Binding> T toSuper(Class<?> clazz, T binding) {
+ Class<?> superClass = clazz;
+ while (superClass != null) {
+ superClass = superClass.getSuperclass();
+ if (superClass != null) {
+ binding.to(superClass);
+ }
+ }
+ for (Class<?> intf : clazz.getInterfaces()){
+ binding.to(intf);
+ }
+ return binding;
+ }
+
+// // Check first if a class is a JAX-RS resource, and only if so check with validation.
+// // This prevents unnecessary warnings being logged for pure CDI beans.
+// private final Cache<Class<?>, Boolean> jaxRsResourceCache = new Cache<>(
+// clazz -> Resource.from(clazz, true) != null && Resource.from(clazz) != null);
+//
+// public boolean isJaxRsResource(Class<?> resource) {
+// return jaxRsResourceCache.apply(resource);
+// }
+
+ private boolean isJaxrs(Class<?> clazz) {
+ return Providers.isJaxRsProvider(clazz) || BeanHelper.isResourceClass(clazz) || isJerseyRegistrable(clazz);
+ }
+
+ private boolean isJerseyRegistrable(Class<?> clazz) {
+ return Feature.class.isAssignableFrom(clazz) || DynamicFeature.class.isAssignableFrom(clazz);
+ }
+
+ private boolean isNotJerseyInternal(Class<?> clazz) {
+ final Package pkg = clazz.getPackage();
+ if (pkg == null) { // Class.getPackage() could return null
+ return false;
+ }
+
+ final String pkgName = pkg.getName();
+ return !pkgName.startsWith("org.glassfish.jersey")
+ || pkgName.startsWith("org.glassfish.jersey.examples")
+ || pkgName.startsWith("org.glassfish.jersey.tests");
+ }
+
+ private boolean matchInitializableInstanceBinding(InitializableInstanceBinding candidate) {
+ for (InitializableInstanceBinding iib : initializableInstanceBindings) {
+ if (iib.matches(candidate).matches()) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ private boolean matchInitializableSupplierInstanceBinding(InitializableSupplierInstanceBinding candidate) {
+ for (InitializableSupplierInstanceBinding isib : initializableSupplierInstanceBindings) {
+ if (isib.matches(candidate).matches()) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+
+ /** To be used by the tests only */
+ public void register(BeforeBeanDiscovery beforeBeanDiscovery, Binding binding) {
+ register(RuntimeType.SERVER, binding);
+ }
+
+ /** To be used by the tests only */
+ public void register(BeforeBeanDiscovery beforeBeanDiscovery, Iterable<Binding> bindings) {
+ register(RuntimeType.SERVER, bindings);
+ }
+
+ private void register(RuntimeType runtimeType, Binding binding) {
+ final AbstractBinder bindings = runtimeType == RuntimeType.CLIENT ? clientBindings : serverBindings;
+ if (InstanceBinding.class.isInstance(binding)) {
+ bindings.bind(InitializableInstanceBinding.from((InstanceBinding) binding));
+ } else if (SupplierInstanceBinding.class.isInstance(binding)) {
+ bindings.bind(InitializableSupplierInstanceBinding.from((SupplierInstanceBinding) binding));
+ } else {
+ bindings.bind(binding);
+ }
+ }
+
+ private void register(RuntimeType runtimeType, Iterable<Binding> bindings) {
+ for (Binding binding : bindings) {
+ register(runtimeType, binding);
+ }
+ }
+
+ private void processRegistrars() {
+ final List<BootstrapPreinitialization> registrars = new LinkedList<>();
+ for (BootstrapPreinitialization registrar : ServiceFinder.find(BootstrapPreinitialization.class)) {
+ registrars.add(registrar);
+ }
+ for (BootstrapPreinitialization registrar : registrars) {
+ registrar.register(RuntimeType.SERVER, serverBindings);
+ }
+
+ for (BootstrapPreinitialization registrar : registrars) {
+ registrar.register(RuntimeType.CLIENT, clientBindings);
+ }
+ }
+
+ InjectionManager getInjectionManager(RuntimeType runtimeType) {
+ if (RuntimeType.CLIENT == runtimeType) {
+ return registrationDone.get()
+ ? new CdiClientInjectionManager(beanManagerSupplier.get(), mergedBindings)
+ : clientBootstrapInjectionManager;
+ } else {
+ return registrationDone.get() ? serverInjectionManager.get() : serverBootstrapInjectionManager;
+ }
+ }
+
+ /**
+ * Injection manager used during the bootstrap. It is used to create the actual beans in the beans manager.
+ * Other InjectionManagers sets the beans (beans binding) by a value provided in runtime.
+ */
+ private class BootstrapInjectionManager implements InjectionManager {
+
+ private final RuntimeType runtimeType;
+
+ private BootstrapInjectionManager(RuntimeType runtimeType) {
+ this.runtimeType = runtimeType;
+ }
+
+ @Override
+ public void completeRegistration() {
+ //noop
+ }
+
+ @Override
+ public void shutdown() {
+ //noop
+ }
+
+ @Override
+ public void register(Binding binding) {
+ BinderRegisterExtension.this.register(runtimeType, binding);
+ }
+
+ @Override
+ public void register(Iterable<Binding> descriptors) {
+ for (Binding binding : descriptors) {
+ register(binding);
+ }
+ }
+
+ @Override
+ public void register(Binder binder) {
+ register(binder.getBindings());
+ }
+
+ @Override
+ public void register(Object provider) throws IllegalArgumentException {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public boolean isRegistrable(Class<?> clazz) {
+ return false;
+ }
+
+ @Override
+ public <T> T createAndInitialize(Class<T> createMe) {
+ if (RequestScope.class == createMe) {
+ return (T) new CdiRequestScope();
+ }
+ if (isNotJerseyInternal(createMe)) {
+ return null;
+ }
+ try {
+ Constructor<T> constructor = createMe.getConstructor();
+ return constructor.newInstance();
+ } catch (NoSuchMethodException | IllegalAccessException | InstantiationException | InvocationTargetException e) {
+ return null;
+ }
+ }
+
+ @Override
+ public <T> T create(Class<T> createMe) {
+ return createAndInitialize(createMe);
+ }
+
+ @Override
+ public <T> List<ServiceHolder<T>> getAllServiceHolders(Class<T> contractOrImpl, Annotation... qualifiers) {
+ return Collections.EMPTY_LIST;
+ }
+
+ @Override
+ public <T> T getInstance(Class<T> contractOrImpl, Annotation... qualifiers) {
+ return getInstance(contractOrImpl);
+ }
+
+ @Override
+ public <T> T getInstance(Class<T> contractOrImpl, String classAnalyzer) {
+ return getInstance(contractOrImpl);
+ }
+
+ @Override
+ public <T> T getInstance(Class<T> contractOrImpl) {
+ return createAndInitialize(contractOrImpl);
+ }
+
+ @Override
+ public <T> T getInstance(Type contractOrImpl) {
+ return (T) createAndInitialize((Class) contractOrImpl);
+ }
+
+ @Override
+ public Object getInstance(ForeignDescriptor foreignDescriptor) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public ForeignDescriptor createForeignDescriptor(Binding binding) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public <T> List<T> getAllInstances(Type contractOrImpl) {
+ final T t = getInstance(contractOrImpl);
+ return t != null ? Collections.singletonList(t) : Collections.EMPTY_LIST;
+ }
+
+ @Override
+ public void inject(Object injectMe) {
+ // noop;
+ }
+
+ @Override
+ public void inject(Object injectMe, String classAnalyzer) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public void preDestroy(Object preDestroyMe) {
+ //noop
+ }
+ }
+
+ /**
+ * AbstractBinder that supports calling {@link #getBindings()} multiple times by caching the result.
+ * Each additional binding is added to the cache by the next call of {@link #getBindings()}.
+ * When {@link #setReadOnly()} is called, no additional binding is added to the cache.
+ */
+ private class CachingBinder extends AbstractBinder {
+ private final Ref<InjectionManager> injectionManager;
+ private AbstractBinder temporaryBinder = new TemporaryBinder();
+ private final Collection<Binding> bindings = new LinkedList<>();
+
+ private CachingBinder(Ref<InjectionManager> injectionManager) {
+ this.injectionManager = injectionManager;
+ }
+
+ @Override
+ protected void configure() {
+ // noop
+ }
+
+ @Override
+ public <T> ClassBinding<T> bind(Class<T> serviceType) {
+ return temporaryBinder.bind(serviceType);
+ }
+
+ @Override
+ public Binding bind(Binding binding) {
+ return temporaryBinder.bind(binding);
+ }
+
+ @Override
+ public <T> ClassBinding<T> bindAsContract(GenericType<T> serviceType) {
+ return temporaryBinder.bindAsContract(serviceType);
+ }
+
+ @Override
+ public <T> ClassBinding<T> bindAsContract(Class<T> serviceType) {
+ return temporaryBinder.bindAsContract(serviceType);
+ }
+
+ @Override
+ public ClassBinding<Object> bindAsContract(Type serviceType) {
+ return temporaryBinder.bindAsContract(serviceType);
+ }
+
+ @Override
+ public <T> InstanceBinding<T> bind(T service) {
+ return temporaryBinder.bind(service);
+ }
+
+ @Override
+ public <T> SupplierClassBinding<T> bindFactory(
+ Class<? extends Supplier<T>> supplierType, Class<? extends Annotation> supplierScope) {
+ return temporaryBinder.bindFactory(supplierType, supplierScope);
+ }
+
+ @Override
+ public <T> SupplierClassBinding<T> bindFactory(Class<? extends Supplier<T>> supplierType) {
+ return temporaryBinder.bindFactory(supplierType);
+ }
+
+ @Override
+ public <T> SupplierInstanceBinding<T> bindFactory(Supplier<T> factory) {
+ return temporaryBinder.bindFactory(factory);
+ }
+
+ @Override
+ public <T extends InjectionResolver> InjectionResolverBinding<T> bind(T resolver) {
+ return temporaryBinder.bind(resolver);
+ }
+
+ @Override
+ public Collection<Binding> getBindings() {
+ if (!readOnly) {
+ if (registrationDone.get()) {
+ bindings.addAll(super.getBindings());
+ }
+ final Collection<Binding> newBindings = temporaryBinder.getBindings();
+ for (Binding binding : newBindings) {
+ if (InstanceBinding.class.isAssignableFrom(binding.getClass())) {
+ binding = InitializableInstanceBinding.from((InstanceBinding) binding);
+ } else if (SupplierInstanceBinding.class.isAssignableFrom(binding.getClass())) {
+ binding = InitializableSupplierInstanceBinding.from((SupplierInstanceBinding) binding);
+ }
+ bindings.add(binding);
+ }
+ temporaryBinder = new TemporaryBinder();
+ }
+ return bindings;
+ }
+
+ private boolean readOnly = false;
+
+ void setReadOnly() {
+ readOnly = true;
+ }
+
+ private class TemporaryBinder extends AbstractBinder {
+
+ @Override
+ protected void configure() {
+ // do nothing
+ }
+ }
+ }
+
+ private static class MergedBindings implements Binder {
+ private final AbstractBinder first;
+ private final AbstractBinder second;
+
+
+ private MergedBindings(AbstractBinder first, AbstractBinder second) {
+ this.first = first;
+ this.second = second;
+ }
+
+ public Collection<Binding> getBindings() {
+ final Collection<Binding> firstBindings = first.getBindings();
+ final Collection<Binding> secondBindings = second.getBindings();
+
+ Collection<Binding> merged = new Collection<Binding>() {
+ @Override
+ public int size() {
+ return firstBindings.size() + secondBindings.size();
+ }
+
+ @Override
+ public boolean isEmpty() {
+ return firstBindings.isEmpty() && secondBindings.isEmpty();
+ }
+
+ @Override
+ public boolean contains(Object o) {
+ return firstBindings.contains(o) || secondBindings.contains(o);
+ }
+
+ @Override
+ public Iterator<Binding> iterator() {
+ final Iterator<Binding> firstIterator = firstBindings.iterator();
+ final Iterator<Binding> secondIterator = secondBindings.iterator();
+ return new Iterator<Binding>() {
+ @Override
+ public boolean hasNext() {
+ return firstIterator.hasNext() || secondIterator.hasNext();
+ }
+
+ @Override
+ public Binding next() {
+ return firstIterator.hasNext() ? firstIterator.next() : secondIterator.next();
+ }
+ };
+ }
+
+ // Used by IDE while debugging
+ @Override
+ public Object[] toArray() {
+ Object[] array = new Object[size()];
+ final Iterator<Binding> bindingIterator = iterator();
+ int i = 0;
+ while (bindingIterator.hasNext()) {
+ array[i++] = bindingIterator.next();
+ }
+ return array;
+ }
+
+ @Override
+ public <T> T[] toArray(T[] a) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public boolean add(Binding binding) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public boolean remove(Object o) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public boolean containsAll(Collection<?> c) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public boolean addAll(Collection<? extends Binding> c) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public boolean removeAll(Collection<?> c) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public boolean retainAll(Collection<?> c) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public void clear() {
+ throw new UnsupportedOperationException();
+ }
+ };
+ return merged;
+ }
+ }
+}
diff --git a/incubator/cdi-inject-weld/src/main/java/org/glassfish/jersey/inject/weld/internal/managed/CdiClientInjectionManager.java b/incubator/cdi-inject-weld/src/main/java/org/glassfish/jersey/inject/weld/internal/managed/CdiClientInjectionManager.java
new file mode 100644
index 0000000..46db64b
--- /dev/null
+++ b/incubator/cdi-inject-weld/src/main/java/org/glassfish/jersey/inject/weld/internal/managed/CdiClientInjectionManager.java
@@ -0,0 +1,151 @@
+/*
+ * Copyright (c) 2021 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.inject.weld.internal.managed;
+
+import javax.enterprise.context.spi.CreationalContext;
+import javax.enterprise.inject.spi.Bean;
+import javax.enterprise.inject.spi.BeanManager;
+import javax.ws.rs.RuntimeType;
+
+import org.glassfish.jersey.inject.weld.internal.bean.JerseyBean;
+import org.glassfish.jersey.inject.weld.internal.inject.InitializableInstanceBinding;
+import org.glassfish.jersey.inject.weld.internal.inject.InitializableSupplierInstanceBinding;
+import org.glassfish.jersey.inject.weld.internal.inject.MatchableBinding;
+import org.glassfish.jersey.inject.weld.internal.injector.JerseyClientCreationalContext;
+import org.glassfish.jersey.internal.inject.Binder;
+import org.glassfish.jersey.internal.inject.Binding;
+import org.glassfish.jersey.internal.inject.Bindings;
+import org.glassfish.jersey.internal.inject.InjectionManager;
+import org.glassfish.jersey.internal.inject.InstanceBinding;
+import org.glassfish.jersey.internal.inject.SupplierClassBinding;
+import org.glassfish.jersey.internal.inject.SupplierInstanceBinding;
+import org.jboss.weld.contexts.CreationalContextImpl;
+
+import java.util.Collection;
+import java.util.IdentityHashMap;
+import java.util.Map;
+
+/**
+ * Each Client Runtime has a unique CdiClientInjectionManager, which passes proper {@link Binding} to the Weld.
+ */
+public class CdiClientInjectionManager extends CdiInjectionManager {
+
+ private Map<InitializableInstanceBinding, InitializableInstanceBinding> clientInstanceBindings = new IdentityHashMap<>();
+ private Map<InitializableSupplierInstanceBinding, InitializableSupplierInstanceBinding> clientSupplierInstanceBindings
+ = new IdentityHashMap<>();
+ private Map<SupplierClassBinding, SupplierClassBinding> clientSupplierClassBinding = new IdentityHashMap<>();
+
+ public CdiClientInjectionManager(BeanManager beanManager, Binder bindings) {
+ super(beanManager, bindings);
+ }
+
+ @Override
+ public void register(Binding binding) {
+ if (InstanceBinding.class.isInstance(binding)) {
+ final Collection<Binding> preBindings = getBindings().getBindings();
+ MatchableBinding.Matching<InitializableInstanceBinding> matching = MatchableBinding.Matching.noneMatching();
+ for (Binding preBinding : preBindings) {
+ if (InitializableInstanceBinding.class.isInstance(preBinding)) {
+ matching = matching.better(((InitializableInstanceBinding) preBinding).matches((InstanceBinding) binding));
+ if (matching.isBest()) {
+ break;
+ }
+ }
+ }
+ if (matching.matches()) {
+ final InitializableInstanceBinding clone = matching.getBinding().clone();
+ clone.init(((InstanceBinding) binding).getService());
+ clientInstanceBindings.put(matching.getBinding(), clone);
+ } else {
+ throw new IllegalStateException("Not initialized " + ((InstanceBinding<?>) binding).getService());
+ }
+ } else if (SupplierInstanceBinding.class.isInstance(binding)) {
+ final Collection<Binding> preBindings = getBindings().getBindings();
+ MatchableBinding.Matching<InitializableSupplierInstanceBinding> matching = MatchableBinding.Matching.noneMatching();
+ for (Binding preBinding : preBindings) {
+ if (InitializableSupplierInstanceBinding.class.isInstance(preBinding)) {
+ matching = matching.better(((InitializableSupplierInstanceBinding) preBinding).matchesContracts(binding));
+ if (matching.isBest()) {
+ break;
+ }
+ }
+ }
+ if (matching.matches()) {
+ final InitializableSupplierInstanceBinding clone = matching.getBinding().clone();
+ clone.init(((SupplierInstanceBinding) binding).getSupplier());
+ clientSupplierInstanceBindings.put(matching.getBinding(), clone);
+ } else {
+ throw new IllegalStateException("Not initialized " + ((SupplierInstanceBinding<?>) binding).getSupplier());
+ }
+// } else if (SupplierClassBinding.class.isInstance(binding)) {
+// final Collection<Binding> preBindings = getBindings().getBindings();
+// BindingMatching.Matching<SupplierClassBinding> matching = BindingMatching.Matching.noneMatching();
+// for (Binding preBinding : preBindings) {
+// if (SupplierClassBinding.class.isInstance(preBinding)) {
+// matching = matching.better(BindingMatching.matches(preBinding, binding));
+// if (matching.isBest()) {
+// break;
+// }
+// }
+// }
+// if (matching.matches()) {
+// final SupplierClassBinding clone = BindingCloner.clone((SupplierClassBinding) binding);
+// clientSupplierClassBinding.put(matching.getBinding(), clone);
+// } else {
+// throw new IllegalStateException("Not initialized " + ((SupplierInstanceBinding<?>) binding).getSupplier());
+// }
+ }
+ }
+
+ public InitializableInstanceBinding getInjectionManagerBinding(InitializableInstanceBinding binding) {
+ InitializableInstanceBinding clientBinding = clientInstanceBindings.get(binding);
+ return clientBinding != null ? clientBinding : binding;
+ }
+
+ public InitializableSupplierInstanceBinding getInjectionManagerBinding(InitializableSupplierInstanceBinding binding) {
+ InitializableSupplierInstanceBinding clientBinding = clientSupplierInstanceBindings.get(binding);
+ return clientBinding != null ? clientBinding : binding;
+ }
+
+ public SupplierClassBinding getInjectionManagerBinding(SupplierClassBinding binding) {
+ SupplierClassBinding clientBinding = clientSupplierClassBinding.get(binding);
+ return clientBinding;
+ }
+
+ @Override
+ public void shutdown() {
+ clientInstanceBindings.clear();
+ }
+
+ @Override
+ protected <T> CreationalContext<T> createCreationalContext(Bean<T> bean) {
+ final CreationalContext<T> ctx = new JerseyClientCreationalContext<T>(
+ (CreationalContextImpl<T>) super.createCreationalContext(bean)).setInjectionManager(this);
+ return ctx;
+ }
+
+ @Override
+ public void completeRegistration() throws IllegalStateException {
+ register(Bindings.service(this).to(InjectionManager.class));
+ }
+
+ @Override
+ protected boolean isRuntimeTypeBean(Bean<?> bean) {
+ return !JerseyBean.class.isInstance(bean) || ((JerseyBean) bean).getRutimeType() == RuntimeType.CLIENT;
+ }
+
+}
diff --git a/incubator/cdi-inject-weld/src/main/java/org/glassfish/jersey/inject/weld/internal/managed/CdiInjectionManager.java b/incubator/cdi-inject-weld/src/main/java/org/glassfish/jersey/inject/weld/internal/managed/CdiInjectionManager.java
new file mode 100644
index 0000000..a99f2f0
--- /dev/null
+++ b/incubator/cdi-inject-weld/src/main/java/org/glassfish/jersey/inject/weld/internal/managed/CdiInjectionManager.java
@@ -0,0 +1,370 @@
+/*
+ * Copyright (c) 2021 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.inject.weld.internal.managed;
+
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Type;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Set;
+
+import javax.enterprise.context.spi.CreationalContext;
+import javax.enterprise.inject.spi.AnnotatedType;
+import javax.enterprise.inject.spi.Bean;
+import javax.enterprise.inject.spi.BeanManager;
+import javax.enterprise.inject.spi.InjectionTarget;
+import javax.enterprise.inject.spi.Unmanaged;
+import javax.inject.Singleton;
+import javax.ws.rs.RuntimeType;
+
+import org.glassfish.jersey.inject.weld.internal.inject.InitializableInstanceBinding;
+import org.glassfish.jersey.inject.weld.internal.inject.InitializableSupplierInstanceBinding;
+import org.glassfish.jersey.inject.weld.internal.bean.JerseyBean;
+import org.glassfish.jersey.inject.weld.internal.inject.MatchableBinding;
+import org.glassfish.jersey.internal.inject.Binder;
+import org.glassfish.jersey.internal.inject.Binding;
+import org.glassfish.jersey.internal.inject.Bindings;
+import org.glassfish.jersey.internal.inject.ClassBinding;
+import org.glassfish.jersey.internal.inject.ForeignDescriptor;
+import org.glassfish.jersey.internal.inject.InjectionManager;
+import org.glassfish.jersey.internal.inject.InstanceBinding;
+import org.glassfish.jersey.internal.inject.ServiceHolder;
+import org.glassfish.jersey.internal.inject.ServiceHolderImpl;
+import org.glassfish.jersey.internal.inject.SupplierInstanceBinding;
+
+/**
+ * Implementation of {@link InjectionManager} used on the server side.
+ */
+@Singleton
+public class CdiInjectionManager implements InjectionManager {
+
+ private final BeanManager beanManager;
+ private final Binder bindings;
+ private boolean isCompleted = false;
+ Set<Class<?>> managedBeans;
+
+ // Keeps all binders and bindings added to the InjectionManager during the bootstrap.
+
+ public CdiInjectionManager(BeanManager beanManager, Binder bindings) {
+ this.beanManager = beanManager;
+ this.bindings = bindings;
+ }
+
+ @Override
+ public void register(Binding binding) {
+ if (isManagedClass(binding)) {
+ return;
+ }
+ if (InstanceBinding.class.isInstance(binding)) {
+ final Collection<Binding> preBindings = bindings.getBindings();
+ MatchableBinding.Matching<InitializableInstanceBinding> matching = MatchableBinding.Matching.noneMatching();
+ for (Binding preBinding : preBindings) {
+ if (InitializableInstanceBinding.class.isInstance(preBinding)) {
+ matching = matching.better(((InitializableInstanceBinding) preBinding).matches((InstanceBinding) binding));
+ if (matching.isBest()) {
+ break;
+ }
+ }
+ }
+ if (matching.matches()) {
+ matching.getBinding().init(((InstanceBinding) binding).getService());
+ } else if (findClassBinding(binding.getImplementationType()) == null) {
+ throw new IllegalStateException("Not initialized " + ((InstanceBinding<?>) binding).getService());
+ }
+ } else if (SupplierInstanceBinding.class.isInstance(binding)) {
+ final Collection<Binding> preBindings = bindings.getBindings();
+ MatchableBinding.Matching<InitializableSupplierInstanceBinding> matching = MatchableBinding.Matching.noneMatching();
+ for (Binding preBinding : preBindings) {
+ if (InitializableSupplierInstanceBinding.class.isInstance(preBinding)) {
+ matching = matching.better(
+ ((InitializableSupplierInstanceBinding) preBinding).matches((SupplierInstanceBinding) binding));
+ if (matching.isBest()) {
+ break;
+ }
+ }
+ }
+ if (matching.matches()) {
+ matching.getBinding().init(((SupplierInstanceBinding) binding).getSupplier());
+ } else {
+ throw new IllegalStateException("Not initialized " + ((SupplierInstanceBinding<?>) binding).getSupplier());
+ }
+ } else if (ClassBinding.class.isInstance(binding)) {
+ if (findClassBinding(binding.getImplementationType()) == null) {
+// final Collection<Binding> preBindings = bindings.getBindings();
+// boolean found = false;
+// for (Binding preBinding : preBindings) {
+// if (ClassBinding.class.isInstance(preBinding)
+// && ((ClassBinding) preBinding).getImplementationType()
+// .equals(((ClassBinding) binding).getImplementationType())) {
+// found = true;
+// break;
+// }
+// }
+// if (!found) {
+ throw new IllegalStateException("ClassBinding for " + binding.getImplementationType() + " not preregistered");
+ }
+ }
+ }
+
+ private <T> ClassBinding<T> findClassBinding(Class<T> implementationType) {
+ final Collection<Binding> preBindings = bindings.getBindings();
+ boolean found = false;
+ for (Binding preBinding : preBindings) {
+ if (ClassBinding.class.isInstance(preBinding)
+ && ((ClassBinding) preBinding).getImplementationType().equals(implementationType)) {
+ return (ClassBinding<T>) preBinding;
+ }
+ }
+ return null;
+ }
+
+ private boolean isManagedClass(Binding binding) {
+ return managedBeans != null
+ && binding.getImplementationType() != null
+ && (managedBeans.contains(binding.getImplementationType())
+ || (managedBeans.contains(binding.getImplementationType().getSuperclass())));
+ }
+
+ @Override
+ public void register(Iterable<Binding> bindings) {
+ for (Binding binding : bindings) {
+ register(binding);
+ }
+ }
+
+ @Override
+ public void register(Binder binder) {
+ for (Binding binding : Bindings.getBindings(this, binder)) {
+ register(binding);
+ }
+ }
+
+ @Override
+ public void register(Object provider) throws IllegalArgumentException {
+ throw new IllegalArgumentException(LocalizationMessages.CDI_2_PROVIDER_NOT_REGISTRABLE(provider.getClass()));
+ }
+
+ @Override
+ public boolean isRegistrable(Class<?> clazz) {
+ return false;
+ }
+
+ @Override
+ public <T> T create(Class<T> createMe) {
+ Unmanaged.UnmanagedInstance<T> unmanaged = new Unmanaged<>(createMe).newInstance();
+ return unmanaged.produce().get();
+ }
+
+ @Override
+ public <T> T createAndInitialize(Class<T> createMe) {
+ Unmanaged.UnmanagedInstance<T> unmanaged = new Unmanaged<>(createMe).newInstance();
+ return unmanaged.produce()
+ .inject()
+ .postConstruct()
+ .get();
+ }
+
+ @Override
+ @SuppressWarnings("unchecked")
+ public <T> List<ServiceHolder<T>> getAllServiceHolders(Class<T> contractOrImpl, Annotation... qualifiers) {
+ List<ServiceHolder<T>> result = new ArrayList<>();
+ for (Bean<?> bean : beanManager.getBeans(contractOrImpl, qualifiers)) {
+
+ if (!isRuntimeTypeBean(bean)) {
+ continue;
+ }
+
+ CreationalContext<?> ctx = createCreationalContext(bean);
+ T reference = (T) beanManager.getReference(bean, contractOrImpl, ctx);
+
+ int rank = 1;
+ if (bean instanceof JerseyBean) {
+ rank = ((JerseyBean) bean).getRank();
+ }
+
+ result.add(new ServiceHolderImpl<>(reference, (Class<T>) bean.getBeanClass(), bean.getTypes(), rank));
+ }
+ return result;
+ }
+
+ @Override
+ public <T> T getInstance(Class<T> contractOrImpl, Annotation... qualifiers) {
+ return getInstanceInternal(contractOrImpl, qualifiers);
+ }
+
+ @Override
+ public <T> T getInstance(Class<T> contractOrImpl) {
+ return getInstanceInternal(contractOrImpl);
+ }
+
+ @Override
+ public <T> T getInstance(Type contractOrImpl) {
+ return getInstanceInternal(contractOrImpl);
+ }
+
+ @SuppressWarnings("unchecked")
+ protected <T> T getInstanceInternal(Type contractOrImpl, Annotation... qualifiers) {
+// if (contractOrImpl.getTypeName().contains("HelloResource")) {
+// T t = (T) CDI.current().select((Class) contractOrImpl, qualifiers).get();
+// try {
+// System.out.println(t.getClass().getMethod("hello").invoke(t));
+//// t.getClass().getMethod("hello").invoke(t);
+// } catch (IllegalAccessException e) {
+// e.printStackTrace();
+// } catch (InvocationTargetException e) {
+// e.printStackTrace();
+// } catch (NoSuchMethodException e) {
+// e.printStackTrace();
+// }
+// return t;
+// }
+ Set<Bean<?>> beans = beanManager.getBeans(contractOrImpl, qualifiers);
+ if (beans.isEmpty()) {
+ return null; //ScopesTest
+ }
+
+ final Iterator<?> beansIterator = beans.iterator();
+ Bean<?> bean = (Bean<?>) beansIterator.next();
+ while (beansIterator.hasNext() && !JerseyBean.class.isInstance(bean) && !isRuntimeTypeBean(bean)) {
+ bean = (Bean<?>) beansIterator.next(); // prefer Jersey binding
+ }
+ CreationalContext<T> ctx = createCreationalContext((Bean<T>) bean);
+ return (T) beanManager.getReference(bean, contractOrImpl, ctx);
+ }
+
+ @Override
+ @SuppressWarnings("unchecked")
+ public Object getInstance(ForeignDescriptor foreignDescriptor) {
+ Bean bean = (Bean) foreignDescriptor.get();
+ CreationalContext ctx = createCreationalContext(bean);
+ return bean.create(ctx);
+ }
+
+ @Override
+ @SuppressWarnings("unchecked")
+ public ForeignDescriptor createForeignDescriptor(Binding binding) {
+ Class<?> clazz;
+ if (ClassBinding.class.isAssignableFrom(binding.getClass())) {
+ clazz = ((ClassBinding<?>) binding).getService();
+ } else if (InstanceBinding.class.isAssignableFrom(binding.getClass())) {
+ clazz = ((InstanceBinding<?>) binding).getService().getClass();
+ } else {
+ throw new RuntimeException(
+ org.glassfish.jersey.internal.LocalizationMessages
+ .UNKNOWN_DESCRIPTOR_TYPE(binding.getClass().getSimpleName()));
+ }
+
+ Set<Bean<?>> beans = beanManager.getBeans(clazz);
+ if (beans.isEmpty()) {
+ return null;
+ }
+
+ Bean bean = beans.iterator().next();
+ CreationalContext ctx = createCreationalContext(bean);
+ return ForeignDescriptor.wrap(bean, instance -> bean.destroy(instance, ctx));
+ }
+
+ @Override
+ @SuppressWarnings("unchecked")
+ public <T> List<T> getAllInstances(Type contractOrImpl) {
+ List<T> result = new ArrayList<>();
+ for (Bean<?> bean : beanManager.getBeans(contractOrImpl)) {
+ CreationalContext<?> ctx = createCreationalContext(bean);
+ Object reference = beanManager.getReference(bean, contractOrImpl, ctx);
+ result.add((T) reference);
+ }
+ return result;
+ }
+
+ @Override
+ @SuppressWarnings("unchecked")
+ public void inject(Object instance) {
+ AnnotatedType annotatedType = beanManager.createAnnotatedType((Class) instance.getClass());
+ InjectionTarget injectionTarget = beanManager.createInjectionTarget(annotatedType);
+ CreationalContext context = createCreationalContext(null);
+ injectionTarget.inject(instance, context);
+ }
+
+ @Override
+ public void preDestroy(Object preDestroyMe) {
+ }
+
+ @Override
+ public void completeRegistration() throws IllegalStateException {
+// bindings.bind(Bindings.service(this).to(InjectionManager.class));
+// bindings.install(new ContextInjectionResolverImpl.Binder(this::getBeanManager));
+//
+// this.beanManager = new DefaultBeanManagerProvider().getBeanManager();
+// beanManager = new DefaultBeanManagerProvider().getBeanManager();
+//
+// AbstractBinder masterBinder = beanManager.getExtension(SeBeanRegisterExtension.class).bindings;
+// masterBinder.getBindings().addAll(bindings.getBindings());
+
+// bindings.bind(Bindings.service(this).to(InjectionManager.class));
+// bindings.install(new ContextInjectionResolverImpl.Binder(this::getBeanManager));
+
+ if (!isCompleted) {
+ register(Bindings.service(this).to(InjectionManager.class));
+ isCompleted = false;
+ }
+ }
+
+ @Override
+ public void shutdown() {
+
+ }
+
+ protected Binder getBindings() {
+ return bindings;
+ }
+
+ protected BeanManager getBeanManager() {
+ return beanManager;
+ }
+
+ protected <T> CreationalContext<T> createCreationalContext(Bean<T> bean) {
+ return (CreationalContext<T>) beanManager.createCreationalContext(bean);
+ }
+
+// protected void registerInjectionResolver(InjectionResolverBinding<?> injectionResolverBinding) {
+// // beanManager.getExtension(BinderRegisterExtension.class).addInjectionResolver(injectionResolverBinding.getResolver());
+// }
+
+ /**
+ * Identifies Jersey beans that are from different runtime (CLIENT vs SERVER). Used to exclude Jersey beans of incorrect
+ * {@link RuntimeType}.
+ * @param bean the given CDI bean.
+ * @return true iff the given bean is not a Jersey Bean or the Jersey Bean is of the proper {@code RuntimeType}.
+ */
+ protected boolean isRuntimeTypeBean(Bean<?> bean) {
+ return !JerseyBean.class.isInstance(bean) || ((JerseyBean) bean).getRutimeType() == RuntimeType.SERVER;
+ }
+
+ @Override
+ public void inject(Object injectMe, String classAnalyzer) {
+ // TODO: Used only in legacy CDI integration.
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public <T> T getInstance(Class<T> contractOrImpl, String classAnalyzer) {
+ // TODO: Used only in legacy CDI integration.
+ throw new UnsupportedOperationException();
+ }
+}
diff --git a/incubator/cdi-inject-weld/src/main/java/org/glassfish/jersey/inject/weld/internal/managed/CdiInjectionManagerFactoryBase.java b/incubator/cdi-inject-weld/src/main/java/org/glassfish/jersey/inject/weld/internal/managed/CdiInjectionManagerFactoryBase.java
new file mode 100644
index 0000000..c0c48f6
--- /dev/null
+++ b/incubator/cdi-inject-weld/src/main/java/org/glassfish/jersey/inject/weld/internal/managed/CdiInjectionManagerFactoryBase.java
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2021 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.inject.weld.internal.managed;
+
+import javax.enterprise.inject.spi.BeanManager;
+import javax.ws.rs.RuntimeType;
+
+import org.glassfish.jersey.internal.inject.InjectionManager;
+import org.glassfish.jersey.internal.inject.InjectionManagerFactory;
+
+/**
+ * CDI Injection Manager Factory base class that holds the current bean manager.
+ */
+public abstract class CdiInjectionManagerFactoryBase implements InjectionManagerFactory {
+ private static BeanManager beanManager;
+
+ /* package */ static void setBeanManager(BeanManager bm) {
+ beanManager = bm;
+ }
+
+ protected static InjectionManager getInjectionManager(RuntimeType runtimeType) {
+ return beanManager.getExtension(BinderRegisterExtension.class).getInjectionManager(runtimeType);
+ }
+}
diff --git a/incubator/cdi-inject-weld/src/main/java/org/glassfish/jersey/inject/weld/internal/managed/ClientBootstrapPreinitialization.java b/incubator/cdi-inject-weld/src/main/java/org/glassfish/jersey/inject/weld/internal/managed/ClientBootstrapPreinitialization.java
new file mode 100644
index 0000000..e82f0e0
--- /dev/null
+++ b/incubator/cdi-inject-weld/src/main/java/org/glassfish/jersey/inject/weld/internal/managed/ClientBootstrapPreinitialization.java
@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 2021 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.inject.weld.internal.managed;
+
+import javax.inject.Inject;
+import javax.inject.Provider;
+import javax.ws.rs.RuntimeType;
+import javax.ws.rs.client.ClientBuilder;
+
+import org.glassfish.jersey.client.ClientConfig;
+import org.glassfish.jersey.client.ClientRequest;
+import org.glassfish.jersey.client.JerseyClient;
+import org.glassfish.jersey.inject.weld.spi.BootstrapPreinitialization;
+import org.glassfish.jersey.internal.PropertiesDelegate;
+import org.glassfish.jersey.internal.inject.AbstractBinder;
+import org.glassfish.jersey.internal.inject.ReferencingFactory;
+import org.glassfish.jersey.internal.util.collection.Ref;
+
+import java.util.function.Supplier;
+
+/**
+ * Jersey Client Runtime pre-initialization implementation.
+ */
+// TODO: put to a proper Jersey module
+public class ClientBootstrapPreinitialization implements BootstrapPreinitialization {
+
+ @Override
+ public void register(RuntimeType runtimeType, AbstractBinder binder) {
+ if (runtimeType == RuntimeType.SERVER) {
+ return;
+ }
+
+ ClientConfig config = new ClientConfig();
+ JerseyClient client = (JerseyClient) ClientBuilder.newClient(config);
+ client.getConfiguration().getClientExecutor();
+ }
+}
diff --git a/incubator/cdi-inject-weld/src/main/java/org/glassfish/jersey/inject/weld/internal/managed/ServerBootstrapPreinitialization.java b/incubator/cdi-inject-weld/src/main/java/org/glassfish/jersey/inject/weld/internal/managed/ServerBootstrapPreinitialization.java
new file mode 100644
index 0000000..a35f806
--- /dev/null
+++ b/incubator/cdi-inject-weld/src/main/java/org/glassfish/jersey/inject/weld/internal/managed/ServerBootstrapPreinitialization.java
@@ -0,0 +1,649 @@
+/*
+ * Copyright (c) 2021 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.inject.weld.internal.managed;
+
+import javax.inject.Inject;
+import javax.inject.Provider;
+import javax.inject.Singleton;
+import javax.servlet.Filter;
+import javax.servlet.FilterConfig;
+import javax.servlet.FilterRegistration;
+import javax.servlet.RequestDispatcher;
+import javax.servlet.Servlet;
+import javax.servlet.ServletConfig;
+import javax.servlet.ServletContext;
+import javax.servlet.ServletException;
+import javax.servlet.ServletRegistration;
+import javax.servlet.SessionCookieConfig;
+import javax.servlet.SessionTrackingMode;
+import javax.servlet.descriptor.JspConfigDescriptor;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import javax.ws.rs.RuntimeType;
+import javax.ws.rs.core.Configuration;
+import javax.ws.rs.core.FeatureContext;
+import javax.ws.rs.core.GenericType;
+
+import org.glassfish.grizzly.http.server.Request;
+import org.glassfish.grizzly.http.server.Response;
+import org.glassfish.jersey.inject.weld.spi.BootstrapPreinitialization;
+import org.glassfish.jersey.internal.ServiceFinderBinder;
+import org.glassfish.jersey.internal.inject.AbstractBinder;
+import org.glassfish.jersey.internal.inject.Binding;
+import org.glassfish.jersey.internal.inject.ClassBinding;
+import org.glassfish.jersey.internal.inject.ReferencingFactory;
+import org.glassfish.jersey.internal.spi.AutoDiscoverable;
+import org.glassfish.jersey.internal.util.collection.Ref;
+import org.glassfish.jersey.model.internal.CommonConfig;
+import org.glassfish.jersey.model.internal.ComponentBag;
+import org.glassfish.jersey.process.internal.RequestScoped;
+import org.glassfish.jersey.server.wadl.WadlFeature;
+import org.glassfish.jersey.server.wadl.processor.OptionsMethodProcessor;
+import org.glassfish.jersey.server.wadl.processor.WadlModelProcessor;
+import org.glassfish.jersey.servlet.WebConfig;
+import org.glassfish.jersey.servlet.spi.AsyncContextDelegateProvider;
+import org.glassfish.jersey.servlet.spi.FilterUrlMappingsProvider;
+
+import java.io.InputStream;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.util.Collections;
+import java.util.Enumeration;
+import java.util.EventListener;
+import java.util.Map;
+import java.util.Set;
+
+
+/**
+ * Jersey server side pre-initialization implementation.
+ */
+// TODO : put to a proper module
+public class ServerBootstrapPreinitialization implements BootstrapPreinitialization {
+
+
+ /**
+ * Referencing factory for Grizzly request.
+ */
+ private static class GrizzlyRequestReferencingFactory extends ReferencingFactory<Request> {
+
+ @Inject
+ public GrizzlyRequestReferencingFactory(final Provider<Ref<Request>> referenceFactory) {
+ super(referenceFactory);
+ }
+ }
+
+ /**
+ * Referencing factory for Grizzly response.
+ */
+ private static class GrizzlyResponseReferencingFactory extends ReferencingFactory<Response> {
+
+ @Inject
+ public GrizzlyResponseReferencingFactory(final Provider<Ref<Response>> referenceFactory) {
+ super(referenceFactory);
+ }
+ }
+
+ @SuppressWarnings("JavaDoc")
+ private static class HttpServletRequestReferencingFactory extends ReferencingFactory<HttpServletRequest> {
+
+ @Inject
+ public HttpServletRequestReferencingFactory(final Provider<Ref<HttpServletRequest>> referenceFactory) {
+ super(referenceFactory);
+ }
+ }
+
+ @SuppressWarnings("JavaDoc")
+ private static class HttpServletResponseReferencingFactory extends ReferencingFactory<HttpServletResponse> {
+
+ @Inject
+ public HttpServletResponseReferencingFactory(final Provider<Ref<HttpServletResponse>> referenceFactory) {
+ super(referenceFactory);
+ }
+ }
+
+ private static class WebConfigInitializer implements WebConfig {
+
+ @Override
+ public ConfigType getConfigType() {
+ return ConfigType.ServletConfig;
+ }
+
+ @Override
+ public ServletConfig getServletConfig() {
+ return new ServletConfig() {
+ @Override
+ public String getServletName() {
+ return "Preinit";
+ }
+
+ @Override
+ public ServletContext getServletContext() {
+ return WebConfigInitializer.this.getServletContext();
+ }
+
+ @Override
+ public String getInitParameter(String name) {
+ return null;
+ }
+
+ @Override
+ public Enumeration<String> getInitParameterNames() {
+ return null;
+ }
+ };
+ }
+
+ @Override
+ public FilterConfig getFilterConfig() {
+ return null;
+ }
+
+ @Override
+ public String getName() {
+ return "Preinit";
+ }
+
+ @Override
+ public String getInitParameter(String name) {
+ return getName();
+ }
+
+ @Override
+ public Enumeration getInitParameterNames() {
+ return null;
+ }
+
+ @Override
+ public ServletContext getServletContext() {
+ return new ServletContext() {
+ @Override
+ public String getContextPath() {
+ return null;
+ }
+
+ @Override
+ public ServletContext getContext(String uripath) {
+ return WebConfigInitializer.this.getServletContext();
+ }
+
+ @Override
+ public int getMajorVersion() {
+ return 0;
+ }
+
+ @Override
+ public int getMinorVersion() {
+ return 0;
+ }
+
+ @Override
+ public int getEffectiveMajorVersion() {
+ return 0;
+ }
+
+ @Override
+ public int getEffectiveMinorVersion() {
+ return 0;
+ }
+
+ @Override
+ public String getMimeType(String file) {
+ return null;
+ }
+
+ @Override
+ public Set<String> getResourcePaths(String path) {
+ return null;
+ }
+
+ @Override
+ public URL getResource(String path) throws MalformedURLException {
+ return null;
+ }
+
+ @Override
+ public InputStream getResourceAsStream(String path) {
+ return null;
+ }
+
+ @Override
+ public RequestDispatcher getRequestDispatcher(String path) {
+ return null;
+ }
+
+ @Override
+ public RequestDispatcher getNamedDispatcher(String name) {
+ return null;
+ }
+
+ @Override
+ public Servlet getServlet(String name) throws ServletException {
+ return null;
+ }
+
+ @Override
+ public Enumeration<Servlet> getServlets() {
+ return null;
+ }
+
+ @Override
+ public Enumeration<String> getServletNames() {
+ return null;
+ }
+
+ @Override
+ public void log(String msg) {
+
+ }
+
+ @Override
+ public void log(Exception exception, String msg) {
+
+ }
+
+ @Override
+ public void log(String message, Throwable throwable) {
+
+ }
+
+ @Override
+ public String getRealPath(String path) {
+ return null;
+ }
+
+ @Override
+ public String getServerInfo() {
+ return null;
+ }
+
+ @Override
+ public String getInitParameter(String name) {
+ return null;
+ }
+
+ @Override
+ public Enumeration<String> getInitParameterNames() {
+ return null;
+ }
+
+ @Override
+ public boolean setInitParameter(String name, String value) {
+ return false;
+ }
+
+ @Override
+ public Object getAttribute(String name) {
+ return null;
+ }
+
+ @Override
+ public Enumeration<String> getAttributeNames() {
+ return null;
+ }
+
+ @Override
+ public void setAttribute(String name, Object object) {
+
+ }
+
+ @Override
+ public void removeAttribute(String name) {
+
+ }
+
+ @Override
+ public String getServletContextName() {
+ return null;
+ }
+
+ @Override
+ public ServletRegistration.Dynamic addServlet(String servletName, String className) {
+ return null;
+ }
+
+ @Override
+ public ServletRegistration.Dynamic addServlet(String servletName, Servlet servlet) {
+ return null;
+ }
+
+ @Override
+ public ServletRegistration.Dynamic addServlet(String servletName, Class<? extends Servlet> servletClass) {
+ return null;
+ }
+
+ @Override
+ public ServletRegistration.Dynamic addJspFile(String servletName, String jspFile) {
+ return null;
+ }
+
+ @Override
+ public <T extends Servlet> T createServlet(Class<T> clazz) throws ServletException {
+ return null;
+ }
+
+ @Override
+ public ServletRegistration getServletRegistration(String servletName) {
+ return null;
+ }
+
+ @Override
+ public Map<String, ? extends ServletRegistration> getServletRegistrations() {
+ return null;
+ }
+
+ @Override
+ public FilterRegistration.Dynamic addFilter(String filterName, String className) {
+ return null;
+ }
+
+ @Override
+ public FilterRegistration.Dynamic addFilter(String filterName, Filter filter) {
+ return null;
+ }
+
+ @Override
+ public FilterRegistration.Dynamic addFilter(String filterName, Class<? extends Filter> filterClass) {
+ return null;
+ }
+
+ @Override
+ public <T extends Filter> T createFilter(Class<T> clazz) throws ServletException {
+ return null;
+ }
+
+ @Override
+ public FilterRegistration getFilterRegistration(String filterName) {
+ return null;
+ }
+
+ @Override
+ public Map<String, ? extends FilterRegistration> getFilterRegistrations() {
+ return null;
+ }
+
+ @Override
+ public SessionCookieConfig getSessionCookieConfig() {
+ return null;
+ }
+
+ @Override
+ public void setSessionTrackingModes(Set<SessionTrackingMode> sessionTrackingModes) {
+
+ }
+
+ @Override
+ public Set<SessionTrackingMode> getDefaultSessionTrackingModes() {
+ return null;
+ }
+
+ @Override
+ public Set<SessionTrackingMode> getEffectiveSessionTrackingModes() {
+ return null;
+ }
+
+ @Override
+ public void addListener(String className) {
+
+ }
+
+ @Override
+ public <T extends EventListener> void addListener(T t) {
+
+ }
+
+ @Override
+ public void addListener(Class<? extends EventListener> listenerClass) {
+
+ }
+
+ @Override
+ public <T extends EventListener> T createListener(Class<T> clazz) throws ServletException {
+ return null;
+ }
+
+ @Override
+ public JspConfigDescriptor getJspConfigDescriptor() {
+ return null;
+ }
+
+ @Override
+ public ClassLoader getClassLoader() {
+ return null;
+ }
+
+ @Override
+ public void declareRoles(String... roleNames) {
+
+ }
+
+ @Override
+ public String getVirtualServerName() {
+ return null;
+ }
+
+ @Override
+ public int getSessionTimeout() {
+ return 0;
+ }
+
+ @Override
+ public void setSessionTimeout(int sessionTimeout) {
+
+ }
+
+ @Override
+ public String getRequestCharacterEncoding() {
+ return null;
+ }
+
+ @Override
+ public void setRequestCharacterEncoding(String encoding) {
+
+ }
+
+ @Override
+ public String getResponseCharacterEncoding() {
+ return null;
+ }
+
+ @Override
+ public void setResponseCharacterEncoding(String encoding) {
+
+ }
+ };
+ }
+ }
+
+ private static class PreinitializationFeatureContext implements FeatureContext {
+
+ private final AbstractBinder binder;
+
+ private PreinitializationFeatureContext(AbstractBinder binder) {
+ this.binder = binder;
+ }
+
+ @Override
+ public Configuration getConfiguration() {
+ return new CommonConfig(RuntimeType.SERVER, ComponentBag.INCLUDE_ALL);
+ }
+
+ @Override
+ public FeatureContext property(String name, Object value) {
+ return this;
+ }
+
+ @Override
+ public FeatureContext register(Class<?> componentClass) {
+ binder.bindAsContract(componentClass);
+ return this;
+ }
+
+ @Override
+ public FeatureContext register(Class<?> componentClass, int priority) {
+ binder.bindAsContract(componentClass).ranked(priority);
+ return this;
+ }
+
+ @Override
+ public FeatureContext register(Class<?> componentClass, Class<?>... contracts) {
+ final ClassBinding binding = binder.bind(componentClass);
+ if (contracts != null) {
+ for (Class<?> contract : contracts) {
+ binding.to(contract);
+ }
+ }
+ return this;
+ }
+
+ @Override
+ public FeatureContext register(Class<?> componentClass, Map<Class<?>, Integer> contracts) {
+ for (Map.Entry<Class<?>, Integer> contract : contracts.entrySet()) {
+ final AbstractBinder abstractBinder = new AbstractBinder() {
+ @Override
+ protected void configure() {
+ }
+ };
+ final ClassBinding binding = abstractBinder.bind(componentClass);
+ binding.to(contract.getKey()).ranked(contract.getValue());
+ binder.install(abstractBinder);
+ }
+ return this;
+ }
+
+ @Override
+ public FeatureContext register(Object component) {
+ if (AbstractBinder.class.isInstance(component)) {
+ binder.install((AbstractBinder) component);
+ } else {
+ binder.bind(component).to(component.getClass());
+ }
+ return this;
+ }
+
+ @Override
+ public FeatureContext register(Object component, int priority) {
+ binder.bind(component).to(component.getClass()).ranked(priority);
+ return this;
+ }
+
+ @Override
+ public FeatureContext register(Object component, Class<?>... contracts) {
+ Binding binding = binder.bind(component);
+ if (contracts != null) {
+ for (Class<?> contract : contracts) {
+ binding.to(contract);
+ }
+ }
+ return this;
+ }
+
+ @Override
+ public FeatureContext register(Object component, Map<Class<?>, Integer> contracts) {
+ for (Map.Entry<Class<?>, Integer> contract : contracts.entrySet()) {
+ final AbstractBinder abstractBinder = new AbstractBinder() {
+ @Override
+ protected void configure() {
+ }
+ };
+ final Binding binding = abstractBinder.bind(component);
+ binding.to(contract.getKey()).ranked(contract.getValue());
+ binder.install(abstractBinder);
+ }
+ return this;
+ }
+ }
+
+ @Override
+ public void register(RuntimeType runtimeType, AbstractBinder binder) {
+// binder.install(new MessagingBinders.MessageBodyProviders(null, RuntimeType.SERVER),
+// new MessagingBinders.HeaderDelegateProviders());
+//
+// // Server Binder
+// binder.install(new MappableExceptionWrapperInterceptor.Binder(),
+// new MonitoringContainerListener.Binder());
+// binder.bind(ChunkedResponseWriter.class).to(MessageBodyWriter.class).in(Singleton.class);
+// binder.bind(JsonWithPaddingInterceptor.class).to(WriterInterceptor.class).in(Singleton.class);
+
+ if (runtimeType == RuntimeType.SERVER) {
+ // new ApplicationHandler(new ResourceConfig());
+
+ //grizzly
+ binder.bindFactory(GrizzlyRequestReferencingFactory.class).to(Request.class)
+ .proxy(false).in(RequestScoped.class);
+ binder.bindFactory(ReferencingFactory.<Request>referenceFactory()).to(new GenericType<Ref<Request>>() {})
+ .in(RequestScoped.class);
+
+ binder.bindFactory(GrizzlyResponseReferencingFactory.class).to(Response.class)
+ .proxy(true).proxyForSameScope(false).in(RequestScoped.class);
+ binder.bindFactory(ReferencingFactory.<Response>referenceFactory()).to(new GenericType<Ref<Response>>() {})
+ .in(RequestScoped.class);
+
+ // servlet
+ binder.bindFactory(HttpServletRequestReferencingFactory.class).to(HttpServletRequest.class)
+ .proxy(true).proxyForSameScope(false).in(RequestScoped.class);
+
+ binder.bindFactory(ReferencingFactory.referenceFactory())
+ .to(new GenericType<Ref<HttpServletRequest>>() {}).in(RequestScoped.class);
+
+ binder.bindFactory(HttpServletResponseReferencingFactory.class).to(HttpServletResponse.class)
+ .proxy(true).proxyForSameScope(false).in(RequestScoped.class);
+ binder.bindFactory(ReferencingFactory.referenceFactory())
+ .to(new GenericType<Ref<HttpServletResponse>>() {}).in(RequestScoped.class);
+
+ final WebConfig webConfig = new WebConfigInitializer();
+ final Map<String, Object> applicationProperties = Collections.EMPTY_MAP;
+
+ binder.bindFactory(() -> webConfig.getServletContext()).to(ServletContext.class).in(Singleton.class);
+ binder.bindFactory(() -> webConfig).to(WebConfig.class).in(Singleton.class);
+ binder.install(
+ new ServiceFinderBinder<>(AsyncContextDelegateProvider.class, applicationProperties, RuntimeType.SERVER));
+ binder.install(
+ new ServiceFinderBinder<>(FilterUrlMappingsProvider.class, applicationProperties, RuntimeType.SERVER));
+
+ final ServletConfig servletConfig = webConfig.getServletConfig();
+ binder.bindFactory(() -> servletConfig).to(ServletConfig.class).in(Singleton.class);
+
+ // WADL TODO put to a proper module
+ try {
+ new WadlFeature().configure(new PreinitializationFeatureContext(binder) {
+ @Override
+ public FeatureContext register(Class<?> componentClass) {
+ if (WadlModelProcessor.class.isAssignableFrom(componentClass)) {
+ super.register(WadlModelProcessor.OptionsHandler.class);
+ }
+ super.register(componentClass);
+ return this;
+ }
+ });
+ } catch (Exception e) {
+
+ }
+ try {
+ Class[] classes = OptionsMethodProcessor.class.getDeclaredClasses();
+ for (Class clz : classes) {
+ binder.bindAsContract(clz);
+ }
+ } catch (Exception e) {
+
+ }
+ }
+
+//
+// //ApplicationConfigurator
+// binder.bind(new InitializableInstanceBinding((Application) null).to(Application.class));
+ }
+}
diff --git a/incubator/cdi-inject-weld/src/main/java/org/glassfish/jersey/inject/weld/internal/managed/WrappingInjectionManager.java b/incubator/cdi-inject-weld/src/main/java/org/glassfish/jersey/inject/weld/internal/managed/WrappingInjectionManager.java
new file mode 100644
index 0000000..a3bea1a
--- /dev/null
+++ b/incubator/cdi-inject-weld/src/main/java/org/glassfish/jersey/inject/weld/internal/managed/WrappingInjectionManager.java
@@ -0,0 +1,142 @@
+/*
+ * Copyright (c) 2021 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.inject.weld.internal.managed;
+
+import org.glassfish.jersey.internal.inject.Binder;
+import org.glassfish.jersey.internal.inject.Binding;
+import org.glassfish.jersey.internal.inject.ForeignDescriptor;
+import org.glassfish.jersey.internal.inject.InjectionManager;
+import org.glassfish.jersey.internal.inject.ServiceHolder;
+
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Type;
+import java.util.List;
+
+/**
+ * Holder of an InjectionManager that is referenced by Beans created in bootstrap.
+ * The original bootstrap injection manager is replaced by the proper injection manager
+ * after the pre-initialization phase.
+ */
+class WrappingInjectionManager implements InjectionManager {
+
+ private InjectionManager injectionManager;
+
+ WrappingInjectionManager setInjectionManager(InjectionManager injectionManager) {
+ this.injectionManager = injectionManager;
+ return this;
+ }
+
+ @Override
+ public void completeRegistration() {
+ injectionManager.completeRegistration();
+ }
+
+ @Override
+ public void shutdown() {
+ injectionManager.shutdown();
+ }
+
+ @Override
+ public void register(Binding binding) {
+ injectionManager.register(binding);
+ }
+
+ @Override
+ public void register(Iterable<Binding> descriptors) {
+ injectionManager.register(descriptors);
+ }
+
+ @Override
+ public void register(Binder binder) {
+ injectionManager.register(binder);
+ }
+
+ @Override
+ public void register(Object provider) throws IllegalArgumentException {
+ injectionManager.register(provider);
+ }
+
+ @Override
+ public boolean isRegistrable(Class<?> clazz) {
+ return injectionManager.isRegistrable(clazz);
+ }
+
+ @Override
+ public <T> T create(Class<T> createMe) {
+ return injectionManager.create(createMe);
+ }
+
+ @Override
+ public <T> T createAndInitialize(Class<T> createMe) {
+ return injectionManager.createAndInitialize(createMe);
+ }
+
+ @Override
+ public <T> List<ServiceHolder<T>> getAllServiceHolders(Class<T> contractOrImpl, Annotation... qualifiers) {
+ return injectionManager.getAllServiceHolders(contractOrImpl, qualifiers);
+ }
+
+ @Override
+ public <T> T getInstance(Class<T> contractOrImpl, Annotation... qualifiers) {
+ return injectionManager.getInstance(contractOrImpl, qualifiers);
+ }
+
+ @Override
+ public <T> T getInstance(Class<T> contractOrImpl, String classAnalyzer) {
+ return injectionManager.getInstance(contractOrImpl, classAnalyzer);
+ }
+
+ @Override
+ public <T> T getInstance(Class<T> contractOrImpl) {
+ return injectionManager.getInstance(contractOrImpl);
+ }
+
+ @Override
+ public <T> T getInstance(Type contractOrImpl) {
+ return injectionManager.getInstance(contractOrImpl);
+ }
+
+ @Override
+ public Object getInstance(ForeignDescriptor foreignDescriptor) {
+ return injectionManager.getInstance(foreignDescriptor);
+ }
+
+ @Override
+ public ForeignDescriptor createForeignDescriptor(Binding binding) {
+ return injectionManager.createForeignDescriptor(binding);
+ }
+
+ @Override
+ public <T> List<T> getAllInstances(Type contractOrImpl) {
+ return injectionManager.getAllInstances(contractOrImpl);
+ }
+
+ @Override
+ public void inject(Object injectMe) {
+ injectionManager.inject(injectMe);
+ }
+
+ @Override
+ public void inject(Object injectMe, String classAnalyzer) {
+ injectionManager.inject(injectMe, classAnalyzer);
+ }
+
+ @Override
+ public void preDestroy(Object preDestroyMe) {
+ injectionManager.preDestroy(preDestroyMe);
+ }
+}
diff --git a/incubator/cdi-inject-weld/src/main/java/org/glassfish/jersey/inject/weld/internal/scope/CdiRequestContext.java b/incubator/cdi-inject-weld/src/main/java/org/glassfish/jersey/inject/weld/internal/scope/CdiRequestContext.java
new file mode 100644
index 0000000..64b8ebc
--- /dev/null
+++ b/incubator/cdi-inject-weld/src/main/java/org/glassfish/jersey/inject/weld/internal/scope/CdiRequestContext.java
@@ -0,0 +1,103 @@
+/*
+ * Copyright (c) 2021 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.inject.weld.internal.scope;
+
+import java.util.HashMap;
+import java.util.Map;
+import java.util.concurrent.atomic.AtomicInteger;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+import org.glassfish.jersey.internal.util.ExtendedLogger;
+import org.glassfish.jersey.internal.util.LazyUid;
+import org.glassfish.jersey.process.internal.RequestContext;
+
+/**
+ * Implementation of the request context.
+ */
+public final class CdiRequestContext implements RequestContext {
+
+ private static final ExtendedLogger logger =
+ new ExtendedLogger(Logger.getLogger(CdiRequestContext.class.getName()), Level.FINEST);
+
+ /*
+ * Scope instance UUID.
+ *
+ * For performance reasons, it's only generated if toString() method is invoked,
+ * e.g. as part of some low-level logging.
+ */
+ private final LazyUid id = new LazyUid();
+
+ /**
+ * Holds the number of snapshots of this scope.
+ */
+ private final AtomicInteger referenceCounter;
+
+ /**
+ * A map of injectable instances in this scope.
+ */
+ private final Map<String, Object> store;
+
+ CdiRequestContext() {
+ this.store = new HashMap<>();
+ this.referenceCounter = new AtomicInteger(1);
+ }
+
+ Map<String, Object> getStore() {
+ return store;
+ }
+
+ /**
+ * Get a "new" reference of the scope instance. This will increase
+ * the internal reference counter which prevents the scope instance
+ * to be destroyed until a {@link #release()} method is explicitly
+ * called (once per each {@code getReference()} method call).
+ *
+ * @return referenced scope instance.
+ */
+ @Override
+ public RequestContext getReference() {
+ // TODO: replace counter with a phantom reference + reference queue-based solution
+ referenceCounter.incrementAndGet();
+ return this;
+ }
+
+ /**
+ * Release a single reference to the current request scope instance.
+ * <p>
+ * Once all instance references are released, the instance will be recycled.
+ */
+ @Override
+ public void release() {
+ if (referenceCounter.decrementAndGet() < 1) {
+ try {
+ store.clear();
+ } finally {
+ logger.debugLog("Released scope instance {0}", this);
+ }
+ }
+ }
+
+ @Override
+ public String toString() {
+ return "Instance{"
+ + "id=" + id
+ + ", referenceCounter=" + referenceCounter
+ + ", store size=" + store.size()
+ + '}';
+ }
+}
diff --git a/incubator/cdi-inject-weld/src/main/java/org/glassfish/jersey/inject/weld/internal/scope/CdiRequestScope.java b/incubator/cdi-inject-weld/src/main/java/org/glassfish/jersey/inject/weld/internal/scope/CdiRequestScope.java
new file mode 100644
index 0000000..64d2a99
--- /dev/null
+++ b/incubator/cdi-inject-weld/src/main/java/org/glassfish/jersey/inject/weld/internal/scope/CdiRequestScope.java
@@ -0,0 +1,91 @@
+/*
+ * Copyright (c) 2021 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.inject.weld.internal.scope;
+
+import javax.inject.Inject;
+
+import org.glassfish.jersey.process.internal.RequestContext;
+import org.glassfish.jersey.process.internal.RequestScope;
+
+import org.jboss.weld.context.bound.BoundRequestContext;
+
+import java.util.concurrent.Callable;
+
+/**
+ * CDI Request scope implementation using Weld-specific {@link BoundRequestContext} which allows pass on storage for
+ * request-scoped objects.
+ */
+public class CdiRequestScope extends RequestScope {
+
+ @Inject
+ private BoundRequestContext requestContextController;
+
+ @Override
+ public RequestContext createContext() {
+ return new CdiRequestContext();
+ }
+
+ @Override
+ protected void activate(RequestContext context, RequestContext oldContext) {
+ super.activate(context, oldContext);
+
+ if (oldContext != null) {
+ CdiRequestContext oldRequestContext = (CdiRequestContext) oldContext;
+ requestContextController.deactivate();
+ requestContextController.dissociate(oldRequestContext.getStore());
+ }
+
+ CdiRequestContext cdiRequestContext = (CdiRequestContext) context;
+ requestContextController.associate(cdiRequestContext.getStore());
+ requestContextController.activate();
+ }
+
+ @Override
+ protected void resume(RequestContext context) {
+ super.resume(context);
+
+ if (context != null) {
+ CdiRequestContext cdiRequestContext = (CdiRequestContext) context;
+ requestContextController.associate(cdiRequestContext.getStore());
+ requestContextController.activate();
+ }
+ }
+
+ @Override
+ protected void release(RequestContext context) {
+ super.release(context);
+
+ CdiRequestContext cdiRequestContext = (CdiRequestContext) context;
+ requestContextController.invalidate();
+ requestContextController.deactivate();
+ requestContextController.dissociate(cdiRequestContext.getStore());
+ }
+
+ @Override
+ protected void suspend(RequestContext context) {
+ if (context != null) {
+ CdiRequestContext cdiRequestContext = (CdiRequestContext) context;
+ requestContextController.deactivate();
+ requestContextController.dissociate(cdiRequestContext.getStore());
+ }
+ }
+
+ @Override
+ public <T> T runInScope(Callable<T> task) throws Exception {
+ return super.runInScope(task);
+ }
+}
diff --git a/incubator/cdi-inject-weld/src/main/java/org/glassfish/jersey/inject/weld/internal/scope/RequestScopeBean.java b/incubator/cdi-inject-weld/src/main/java/org/glassfish/jersey/inject/weld/internal/scope/RequestScopeBean.java
new file mode 100644
index 0000000..6770060
--- /dev/null
+++ b/incubator/cdi-inject-weld/src/main/java/org/glassfish/jersey/inject/weld/internal/scope/RequestScopeBean.java
@@ -0,0 +1,118 @@
+/*
+ * Copyright (c) 2021 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.inject.weld.internal.scope;
+
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Type;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Set;
+
+import javax.enterprise.context.spi.CreationalContext;
+import javax.enterprise.inject.Any;
+import javax.enterprise.inject.Default;
+import javax.enterprise.inject.spi.AnnotatedType;
+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.util.AnnotationLiteral;
+import javax.inject.Singleton;
+
+import org.glassfish.jersey.process.internal.RequestScope;
+
+/**
+ * CDI Class Bean represents {@link CdiRequestScope}.
+ *
+ * @author Petr Bouda
+ */
+public class RequestScopeBean implements Bean<CdiRequestScope> {
+
+ private final InjectionTarget<CdiRequestScope> injectionTarget;
+
+ /**
+ * Creates a new Jersey-specific {@link javax.enterprise.inject.spi.Bean} instance.
+ */
+ public RequestScopeBean(BeanManager beanManager) {
+ AnnotatedType<CdiRequestScope> annotatedType = beanManager.createAnnotatedType(CdiRequestScope.class);
+ this.injectionTarget = beanManager.createInjectionTarget(annotatedType);
+ }
+
+ @Override
+ public boolean isNullable() {
+ return false;
+ }
+
+ @Override
+ @SuppressWarnings("unchecked")
+ public CdiRequestScope create(CreationalContext<CdiRequestScope> context) {
+ CdiRequestScope instance = injectionTarget.produce(context);
+ injectionTarget.inject(instance, context);
+ injectionTarget.postConstruct(instance);
+ return instance;
+ }
+
+ @Override
+ public void destroy(CdiRequestScope instance, CreationalContext<CdiRequestScope> context) {
+ injectionTarget.preDestroy(instance);
+ injectionTarget.dispose(instance);
+ context.release();
+ }
+
+ @Override
+ public Set<Type> getTypes() {
+ return Collections.singleton(RequestScope.class);
+ }
+
+ @Override
+ public Set<InjectionPoint> getInjectionPoints() {
+ return Collections.emptySet();
+ }
+
+ @Override
+ public Set<Annotation> getQualifiers() {
+ Set<Annotation> qualifiers = new HashSet<>();
+ qualifiers.add(new AnnotationLiteral<Default>() {});
+ qualifiers.add(new AnnotationLiteral<Any>() {});
+ return qualifiers;
+ }
+
+ @Override
+ public Class<? extends Annotation> getScope() {
+ return Singleton.class;
+ }
+
+ @Override
+ public String getName() {
+ return CdiRequestScope.class.getName();
+ }
+
+ @Override
+ public Set<Class<? extends Annotation>> getStereotypes() {
+ return Collections.emptySet();
+ }
+
+ @Override
+ public boolean isAlternative() {
+ return false;
+ }
+
+ @Override
+ public Class<?> getBeanClass() {
+ return CdiRequestScope.class;
+ }
+}
diff --git a/incubator/cdi-inject-weld/src/main/java/org/glassfish/jersey/inject/weld/internal/type/GenericArrayTypeImpl.java b/incubator/cdi-inject-weld/src/main/java/org/glassfish/jersey/inject/weld/internal/type/GenericArrayTypeImpl.java
new file mode 100644
index 0000000..d093e26
--- /dev/null
+++ b/incubator/cdi-inject-weld/src/main/java/org/glassfish/jersey/inject/weld/internal/type/GenericArrayTypeImpl.java
@@ -0,0 +1,94 @@
+/*
+ * Copyright (c) 2021 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.inject.weld.internal.type;
+
+import java.lang.reflect.GenericArrayType;
+import java.lang.reflect.Type;
+
+/**
+ * An implementation of GenericArrayType for those times we need to create this on the fly.
+ *
+ * @author John Wells (john.wells at oracle.com)
+ */
+public class GenericArrayTypeImpl implements GenericArrayType {
+ private final Type genericComponentType;
+
+ /**
+ * Creates the GenericArrayType with the given array type
+ *
+ * @param gct the non-null type for this GenericArrayType
+ */
+ public GenericArrayTypeImpl(Type gct) {
+ genericComponentType = gct;
+ }
+
+ /* (non-Javadoc)
+ * @see java.lang.reflect.GenericArrayType#getGenericComponentType()
+ */
+ @Override
+ public Type getGenericComponentType() {
+ return genericComponentType;
+ }
+
+ @Override
+ public int hashCode() {
+ return genericComponentType.hashCode();
+ }
+
+ /**
+ * Returns true if a is equals to b, or both
+ * and and b are null. Is safe even if
+ * a or b is null. If a or b is null but
+ * the other is not null, this returns false
+ *
+ * @param a A possibly null object to compare
+ * @param b A possibly null object to compare
+ * @return true if equal, false if not
+ */
+ private static boolean safeEquals(Object a, Object b) {
+ if (a == b) {
+ return true;
+ }
+ if (a == null) {
+ return false;
+ }
+ if (b == null) {
+ return false;
+ }
+
+ return a.equals(b);
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (o == null) {
+ return false;
+ }
+ if (!(o instanceof GenericArrayType)) {
+ return false;
+ }
+
+ GenericArrayType other = (GenericArrayType) o;
+
+ return safeEquals(genericComponentType, other.getGenericComponentType());
+ }
+
+ public String toString() {
+ return "GenericArrayTypeImpl(" + genericComponentType + ")";
+ }
+
+}
diff --git a/incubator/cdi-inject-weld/src/main/java/org/glassfish/jersey/inject/weld/internal/type/ParameterizedTypeImpl.java b/incubator/cdi-inject-weld/src/main/java/org/glassfish/jersey/inject/weld/internal/type/ParameterizedTypeImpl.java
new file mode 100644
index 0000000..c358aa2
--- /dev/null
+++ b/incubator/cdi-inject-weld/src/main/java/org/glassfish/jersey/inject/weld/internal/type/ParameterizedTypeImpl.java
@@ -0,0 +1,107 @@
+/*
+ * Copyright (c) 2021 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.inject.weld.internal.type;
+
+import java.lang.reflect.ParameterizedType;
+import java.lang.reflect.Type;
+import java.util.Arrays;
+
+/**
+ * Simple implementation of {@link ParameterizedType}.
+ * <p>
+ * John Wells (john.wells at oracle.com)
+ */
+public class ParameterizedTypeImpl implements ParameterizedType {
+
+ private final Type rawType;
+ private final Type actualTypeArguments[];
+
+ /**
+ * A new parameterized type.
+ *
+ * @param rawType The raw type of this type.
+ * @param actualTypeArguments The actual type arguments.
+ */
+ public ParameterizedTypeImpl(Type rawType, Type... actualTypeArguments) {
+ this.rawType = rawType;
+ this.actualTypeArguments = actualTypeArguments;
+ }
+
+ /* (non-Javadoc)
+ * @see java.lang.reflect.ParameterizedType#getActualTypeArguments()
+ */
+ @Override
+ public Type[] getActualTypeArguments() {
+ return actualTypeArguments;
+ }
+
+ /* (non-Javadoc)
+ * @see java.lang.reflect.ParameterizedType#getRawType()
+ */
+ @Override
+ public Type getRawType() {
+ return rawType;
+ }
+
+ /* (non-Javadoc)
+ * @see java.lang.reflect.ParameterizedType#getOwnerType()
+ * This is only used for top level types
+ */
+ @Override
+ public Type getOwnerType() {
+ return null;
+ }
+
+ @Override
+ public int hashCode() {
+ int retVal = Arrays.hashCode(actualTypeArguments);
+ if (rawType == null) {
+ return retVal;
+ }
+ return retVal ^ rawType.hashCode();
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (o == null) {
+ return false;
+ }
+ if (!(o instanceof ParameterizedType)) {
+ return false;
+ }
+
+ ParameterizedType other = (ParameterizedType) o;
+
+ if (!rawType.equals(other.getRawType())) {
+ return false;
+ }
+
+ Type otherActuals[] = other.getActualTypeArguments();
+
+ if (otherActuals.length != actualTypeArguments.length) {
+ return false;
+ }
+
+ for (int lcv = 0; lcv < otherActuals.length; lcv++) {
+ if (!actualTypeArguments[lcv].equals(otherActuals[lcv])) {
+ return false;
+ }
+ }
+
+ return true;
+ }
+}
diff --git a/incubator/cdi-inject-weld/src/main/java/org/glassfish/jersey/inject/weld/managed/CdiInjectionManagerFactory.java b/incubator/cdi-inject-weld/src/main/java/org/glassfish/jersey/inject/weld/managed/CdiInjectionManagerFactory.java
new file mode 100644
index 0000000..8ea746f
--- /dev/null
+++ b/incubator/cdi-inject-weld/src/main/java/org/glassfish/jersey/inject/weld/managed/CdiInjectionManagerFactory.java
@@ -0,0 +1,78 @@
+/*
+ * Copyright (c) 2021 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.inject.weld.managed;
+
+import javax.annotation.Priority;
+import javax.enterprise.context.spi.CreationalContext;
+import javax.ws.rs.RuntimeType;
+
+import org.glassfish.jersey.client.ClientConfig;
+import org.glassfish.jersey.inject.weld.internal.injector.JerseyClientCreationalContext;
+import org.glassfish.jersey.inject.weld.internal.managed.CdiInjectionManagerFactoryBase;
+import org.glassfish.jersey.internal.inject.InjectionManager;
+import org.glassfish.jersey.internal.inject.InjectionManagerFactory;
+import org.glassfish.jersey.server.ApplicationHandler;
+
+/**
+ * SPI implementation of {@link InjectionManagerFactory} which provides a new instance of CDI {@link InjectionManager}.
+ */
+@Priority(20)
+public class CdiInjectionManagerFactory extends CdiInjectionManagerFactoryBase implements InjectionManagerFactory {
+
+ @Override
+ // TODO deprecate this in favor of #create(Object parent, RuntimeType runtimeType)
+ public InjectionManager create(Object parent) {
+ return create(parent, getRuntimeType());
+ }
+
+ /**
+ * Create injectionManager for {@link RuntimeType#CLIENT or get the existing injection manager for the server}
+ * @param parent Parent injection manager. Not used in this InjectionManagerFactory.
+ * @param runtimeType {@link RuntimeType} to get or create the proper injection manager.
+ * @return The required injection manager instance.
+ */
+ public InjectionManager create(Object parent, RuntimeType runtimeType) {
+ return getInjectionManager(runtimeType);
+ }
+
+ /**
+ * Get the client side InjectionManager stored in the {@link CreationalContext} or the server side InjectionManager.
+ * @param creationalContext {@link CreationalContext} subclass which may hold InjectionManager for the client
+ * @return existing client side injection or server side injection manager.
+ */
+ public static InjectionManager getInjectionManager(CreationalContext<?> creationalContext) {
+ if (JerseyClientCreationalContext.class.isInstance(creationalContext)) {
+ return ((JerseyClientCreationalContext) creationalContext).getInjectionManager();
+ } else {
+ return getInjectionManager(RuntimeType.SERVER);
+ }
+ }
+
+ // TODO refactor to call InjectionManagerFactory#create(Object, RuntimeType);
+ private static RuntimeType getRuntimeType() {
+ Exception e = new RuntimeException();
+ for (StackTraceElement element : e.getStackTrace()) {
+ if (element.getClassName().equals(ClientConfig.class.getName())) {
+ return RuntimeType.CLIENT;
+ }
+ if (element.getClassName().equals(ApplicationHandler.class.getName())) {
+ return RuntimeType.SERVER;
+ }
+ }
+ return RuntimeType.SERVER;
+ }
+}
diff --git a/incubator/cdi-inject-weld/src/main/java/org/glassfish/jersey/inject/weld/spi/BootstrapPreinitialization.java b/incubator/cdi-inject-weld/src/main/java/org/glassfish/jersey/inject/weld/spi/BootstrapPreinitialization.java
new file mode 100644
index 0000000..0c90da5
--- /dev/null
+++ b/incubator/cdi-inject-weld/src/main/java/org/glassfish/jersey/inject/weld/spi/BootstrapPreinitialization.java
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2021 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.inject.weld.spi;
+
+import javax.ws.rs.RuntimeType;
+
+import org.glassfish.jersey.Beta;
+import org.glassfish.jersey.internal.inject.AbstractBinder;
+
+/**
+ * <p>
+ * The entry point for pre-initialize Jersey during bootstrap. Register the beans that are not recognized by the injection
+ * framework to be injected in runtime. Register beans for the specific runtime type into the {@link AbstractBinder}.
+ * </p>
+ */
+@Beta
+public interface BootstrapPreinitialization {
+ /**
+ * Manually register beans that are not automatically recognised by the injection framework.
+ * @param runtimeType
+ * @param binder
+ */
+ void register(RuntimeType runtimeType, AbstractBinder binder);
+}
diff --git a/incubator/cdi-inject-weld/src/main/resources/META-INF/services/javax.enterprise.inject.spi.Extension b/incubator/cdi-inject-weld/src/main/resources/META-INF/services/javax.enterprise.inject.spi.Extension
new file mode 100644
index 0000000..729ccf2
--- /dev/null
+++ b/incubator/cdi-inject-weld/src/main/resources/META-INF/services/javax.enterprise.inject.spi.Extension
@@ -0,0 +1,17 @@
+
+# Copyright (c) 2021 Oracle and/or its affiliates. All rights reserved.
+#
+# This program and the accompanying materials are made available under the
+# terms of the Eclipse Public License v. 2.0, which is available at
+# http://www.eclipse.org/legal/epl-2.0.
+#
+# This Source Code may also be made available under the following Secondary
+# Licenses when the conditions for such availability set forth in the
+# Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+# version 2 with the GNU Classpath Exception, which is available at
+# https://www.gnu.org/software/classpath/license.html.
+#
+# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+#
+
+org.glassfish.jersey.inject.weld.internal.managed.BinderRegisterExtension
\ No newline at end of file
diff --git a/incubator/cdi-inject-weld/src/main/resources/META-INF/services/org.glassfish.jersey.inject.weld.spi.BootstrapPreinitialization b/incubator/cdi-inject-weld/src/main/resources/META-INF/services/org.glassfish.jersey.inject.weld.spi.BootstrapPreinitialization
new file mode 100644
index 0000000..9e2e9ad
--- /dev/null
+++ b/incubator/cdi-inject-weld/src/main/resources/META-INF/services/org.glassfish.jersey.inject.weld.spi.BootstrapPreinitialization
@@ -0,0 +1,17 @@
+#
+# Copyright (c) 2021 Oracle and/or its affiliates. All rights reserved.
+#
+# This program and the accompanying materials are made available under the
+# terms of the Eclipse Public License v. 2.0, which is available at
+# http://www.eclipse.org/legal/epl-2.0.
+#
+# This Source Code may also be made available under the following Secondary
+# Licenses when the conditions for such availability set forth in the
+# Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+# version 2 with the GNU Classpath Exception, which is available at
+# https://www.gnu.org/software/classpath/license.html.
+#
+# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+#
+org.glassfish.jersey.inject.weld.internal.managed.ClientBootstrapPreinitialization
+org.glassfish.jersey.inject.weld.internal.managed.ServerBootstrapPreinitialization
\ No newline at end of file
diff --git a/incubator/cdi-inject-weld/src/main/resources/META-INF/services/org.glassfish.jersey.internal.inject.InjectionManagerFactory b/incubator/cdi-inject-weld/src/main/resources/META-INF/services/org.glassfish.jersey.internal.inject.InjectionManagerFactory
new file mode 100644
index 0000000..71491fa
--- /dev/null
+++ b/incubator/cdi-inject-weld/src/main/resources/META-INF/services/org.glassfish.jersey.internal.inject.InjectionManagerFactory
@@ -0,0 +1,17 @@
+#
+# Copyright (c) 2021 Oracle and/or its affiliates. All rights reserved.
+#
+# This program and the accompanying materials are made available under the
+# terms of the Eclipse Public License v. 2.0, which is available at
+# http://www.eclipse.org/legal/epl-2.0.
+#
+# This Source Code may also be made available under the following Secondary
+# Licenses when the conditions for such availability set forth in the
+# Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+# version 2 with the GNU Classpath Exception, which is available at
+# https://www.gnu.org/software/classpath/license.html.
+#
+# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+#
+
+org.glassfish.jersey.inject.weld.managed.CdiInjectionManagerFactory
diff --git a/incubator/cdi-inject-weld/src/main/resources/org/glassfish/jersey/inject/weld/internal/managed/localization.properties b/incubator/cdi-inject-weld/src/main/resources/org/glassfish/jersey/inject/weld/internal/managed/localization.properties
new file mode 100644
index 0000000..8716ee6
--- /dev/null
+++ b/incubator/cdi-inject-weld/src/main/resources/org/glassfish/jersey/inject/weld/internal/managed/localization.properties
@@ -0,0 +1,18 @@
+#
+# Copyright (c) 2021 Oracle and/or its affiliates. All rights reserved.
+#
+# This program and the accompanying materials are made available under the
+# terms of the Eclipse Public License v. 2.0, which is available at
+# http://www.eclipse.org/legal/epl-2.0.
+#
+# This Source Code may also be made available under the following Secondary
+# Licenses when the conditions for such availability set forth in the
+# Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+# version 2 with the GNU Classpath Exception, which is available at
+# https://www.gnu.org/software/classpath/license.html.
+#
+# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+#
+
+# {0} - full classname
+cdi2.provider.not.registrable=Provider registered to CdiInjectionManager cannot be process because of incompatible type: {0}.
diff --git a/incubator/cdi-inject-weld/src/test/java/org/glassfish/jersey/inject/weld/internal/injector/CachedConstructorAnalyzerTest.java b/incubator/cdi-inject-weld/src/test/java/org/glassfish/jersey/inject/weld/internal/injector/CachedConstructorAnalyzerTest.java
new file mode 100644
index 0000000..eebc20d
--- /dev/null
+++ b/incubator/cdi-inject-weld/src/test/java/org/glassfish/jersey/inject/weld/internal/injector/CachedConstructorAnalyzerTest.java
@@ -0,0 +1,223 @@
+/*
+ * Copyright (c) 2021 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.inject.weld.internal.injector;
+
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Constructor;
+import java.util.Arrays;
+import java.util.Collection;
+
+import javax.enterprise.inject.InjectionException;
+import javax.ws.rs.MatrixParam;
+import javax.ws.rs.PathParam;
+import javax.ws.rs.core.Context;
+
+import org.junit.Test;
+import static org.junit.Assert.assertEquals;
+
+/**
+ * Tests {@link CachedConstructorAnalyzer}.
+ */
+public class CachedConstructorAnalyzerTest {
+
+ private static final Collection<Class<? extends Annotation>> ANNOTATIONS =
+ Arrays.asList(Context.class, PathParam.class);
+
+ @Test
+ public void testDefaultConstructor() {
+ CachedConstructorAnalyzer<DefaultConstructor> analyzer =
+ new CachedConstructorAnalyzer<>(DefaultConstructor.class, ANNOTATIONS);
+
+ assertEquals(0, analyzer.getConstructor().getParameterCount());
+ }
+
+ @Test
+ public void testNoArgsConstructor() {
+ CachedConstructorAnalyzer<NoArgsConstructor> analyzer =
+ new CachedConstructorAnalyzer<>(NoArgsConstructor.class, ANNOTATIONS);
+
+ assertEquals(0, analyzer.getConstructor().getParameterCount());
+ }
+
+ @Test
+ public void testSingleAnnotatedConstructor() {
+ CachedConstructorAnalyzer<SingleAnnotatedConstructor> analyzer =
+ new CachedConstructorAnalyzer<>(SingleAnnotatedConstructor.class, ANNOTATIONS);
+
+ assertEquals(1, analyzer.getConstructor().getParameterCount());
+ }
+
+ @Test
+ public void testSingleMultiAnnotatedConstructor() {
+ CachedConstructorAnalyzer<SingleMultiAnnotatedConstructor> analyzer =
+ new CachedConstructorAnalyzer<>(SingleMultiAnnotatedConstructor.class, ANNOTATIONS);
+
+ assertEquals(2, analyzer.getConstructor().getParameterCount());
+ }
+
+ @Test
+ public void testLargestAnnotatedConstructor() {
+ CachedConstructorAnalyzer<LargestAnnotatedConstructor> analyzer =
+ new CachedConstructorAnalyzer<>(LargestAnnotatedConstructor.class, ANNOTATIONS);
+
+ assertEquals(3, analyzer.getConstructor().getParameterCount());
+ }
+
+ @Test
+ public void testContainsSmallerNonAnnotatedConstructor() {
+ CachedConstructorAnalyzer<ContainsSmallerNonAnnotatedConstructor> analyzer =
+ new CachedConstructorAnalyzer<>(ContainsSmallerNonAnnotatedConstructor.class, ANNOTATIONS);
+
+ assertEquals(2, analyzer.getConstructor().getParameterCount());
+ }
+
+ @Test
+ public void testContainsLargerNonAnnotatedConstructor() {
+ CachedConstructorAnalyzer<ContainsLargerNonAnnotatedConstructor> analyzer =
+ new CachedConstructorAnalyzer<>(ContainsLargerNonAnnotatedConstructor.class, ANNOTATIONS);
+
+ assertEquals(1, analyzer.getConstructor().getParameterCount());
+ }
+
+ @Test
+ public void testSameNonAnnotatedConstructor() {
+ CachedConstructorAnalyzer<SameNonAnnotatedConstructor> analyzer =
+ new CachedConstructorAnalyzer<>(SameNonAnnotatedConstructor.class, ANNOTATIONS);
+
+ assertEquals(1, analyzer.getConstructor().getParameterCount());
+ }
+
+ @Test
+ public void testBothAnnotatedConstructor() {
+ CachedConstructorAnalyzer<BothAnnotatedConstructor> analyzer =
+ new CachedConstructorAnalyzer<>(BothAnnotatedConstructor.class, ANNOTATIONS);
+
+ Constructor<BothAnnotatedConstructor> constructor = analyzer.getConstructor();
+ assertEquals(1, constructor.getParameterCount());
+ assertEquals(Integer.class, constructor.getParameterTypes()[0]);
+ }
+
+ @Test
+ public void testOneNonAnnotatedConstructor() {
+ CachedConstructorAnalyzer<OneNonAnnotatedConstructor> analyzer =
+ new CachedConstructorAnalyzer<>(OneNonAnnotatedConstructor.class, ANNOTATIONS);
+
+ assertEquals(1, analyzer.getConstructor().getParameterCount());
+ }
+
+ @Test
+ public void testMultiAnnotatedConstructor() {
+ CachedConstructorAnalyzer<MultiAnnotatedConstructor> analyzer =
+ new CachedConstructorAnalyzer<>(MultiAnnotatedConstructor.class, ANNOTATIONS);
+
+ assertEquals(2, analyzer.getConstructor().getParameterCount());
+ }
+
+ @Test(expected = InjectionException.class)
+ public void testUnknownAnnotatedConstructor() {
+ new CachedConstructorAnalyzer<>(UnknownAnnotatedConstructor.class, ANNOTATIONS).getConstructor();
+ }
+
+ @Test(expected = InjectionException.class)
+ public void testSingleNonAnnotatedConstructor() {
+ new CachedConstructorAnalyzer<>(SingleNonAnnotatedConstructor.class, ANNOTATIONS).getConstructor();
+ }
+
+ public static class DefaultConstructor {
+ }
+
+ public static class NoArgsConstructor {
+ public NoArgsConstructor() {
+ }
+ }
+
+ public static class SingleNonAnnotatedConstructor {
+ public SingleNonAnnotatedConstructor(String str) {
+ }
+ }
+
+ public static class SingleAnnotatedConstructor {
+ public SingleAnnotatedConstructor(@Context String str) {
+ }
+ }
+
+ public static class SingleMultiAnnotatedConstructor {
+ public SingleMultiAnnotatedConstructor(@Context String str, @PathParam("name") String name) {
+ }
+ }
+
+ public static class LargestAnnotatedConstructor {
+ public LargestAnnotatedConstructor(@Context String str, @PathParam("name") String name, @Context String str2) {
+ }
+
+ public LargestAnnotatedConstructor(@Context String str) {
+ }
+
+ public LargestAnnotatedConstructor(@Context String str, @PathParam("name") String name) {
+ }
+ }
+
+ public static class ContainsSmallerNonAnnotatedConstructor {
+ public ContainsSmallerNonAnnotatedConstructor(String str) {
+ }
+
+ public ContainsSmallerNonAnnotatedConstructor(@Context String str, @PathParam("name") String name) {
+ }
+ }
+
+ public static class ContainsLargerNonAnnotatedConstructor {
+ public ContainsLargerNonAnnotatedConstructor(@Context String str) {
+ }
+
+ public ContainsLargerNonAnnotatedConstructor(String str, String name) {
+ }
+ }
+
+ public static class SameNonAnnotatedConstructor {
+ public SameNonAnnotatedConstructor(@Context String str) {
+ }
+
+ public SameNonAnnotatedConstructor(Integer name) {
+ }
+ }
+
+ public static class BothAnnotatedConstructor {
+ public BothAnnotatedConstructor(@Context String str) {
+ }
+
+ public BothAnnotatedConstructor(@Context Integer name) {
+ }
+ }
+
+ public static class OneNonAnnotatedConstructor {
+ public OneNonAnnotatedConstructor(@Context String str) {
+ }
+
+ public OneNonAnnotatedConstructor(@Context Integer name, String str) {
+ }
+ }
+
+ public static class MultiAnnotatedConstructor {
+ public MultiAnnotatedConstructor(@Context Integer name, @PathParam("str") @Context String str) {
+ }
+ }
+
+ public static class UnknownAnnotatedConstructor {
+ public UnknownAnnotatedConstructor(@Context Integer name, @MatrixParam("matrix") String str) {
+ }
+ }
+}
diff --git a/incubator/cdi-inject-weld/src/test/java/org/glassfish/jersey/inject/weld/internal/injector/JerseyProxyResolverTest.java b/incubator/cdi-inject-weld/src/test/java/org/glassfish/jersey/inject/weld/internal/injector/JerseyProxyResolverTest.java
new file mode 100644
index 0000000..76fcd88
--- /dev/null
+++ b/incubator/cdi-inject-weld/src/test/java/org/glassfish/jersey/inject/weld/internal/injector/JerseyProxyResolverTest.java
@@ -0,0 +1,192 @@
+/*
+ * Copyright (c) 2021 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.inject.weld.internal.injector;
+
+import java.lang.reflect.Field;
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.enterprise.context.ApplicationScoped;
+import javax.enterprise.context.RequestScoped;
+import javax.inject.Singleton;
+import javax.ws.rs.core.Application;
+import javax.ws.rs.core.Context;
+import javax.ws.rs.ext.Providers;
+
+import org.glassfish.jersey.internal.JaxrsProviders;
+import org.glassfish.jersey.internal.inject.Injectee;
+import org.glassfish.jersey.internal.inject.InjecteeImpl;
+import org.glassfish.jersey.internal.inject.InjectionResolver;
+
+import org.junit.Test;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotSame;
+import static org.junit.Assert.assertSame;
+import static org.junit.Assert.assertTrue;
+
+/**
+ * Tests Jersey Proxy Resolver.
+ */
+public class JerseyProxyResolverTest {
+
+ private static Field[] FIELDS = StubForFields.class.getDeclaredFields();
+
+ @Test
+ public void testSignletonIsProxiable() {
+ InjecteeImpl injectee = new InjecteeImpl();
+ injectee.setInjecteeClass(TestSingleton.class);
+ injectee.setParentClassScope(Singleton.class);
+
+ JerseyProxyResolver resolver = new JerseyProxyResolver();
+ assertTrue(resolver.isProxiable(injectee));
+ }
+
+ @Test
+ public void testApplicationScopeIsProxiable() {
+ InjecteeImpl injectee = new InjecteeImpl();
+ injectee.setInjecteeClass(TestApplicationScope.class);
+ injectee.setParentClassScope(ApplicationScoped.class);
+
+ JerseyProxyResolver resolver = new JerseyProxyResolver();
+ assertTrue(resolver.isProxiable(injectee));
+ }
+
+ @Test
+ public void testRequestScopeFromNonAnnotatedIsNotProxiable() {
+ InjecteeImpl injectee = new InjecteeImpl();
+ injectee.setInjecteeClass(TestNonAnnotatedRequestScope.class);
+ injectee.setParentClassScope(RequestScoped.class);
+
+ JerseyProxyResolver resolver = new JerseyProxyResolver();
+ assertFalse(resolver.isProxiable(injectee));
+ }
+
+ @Test
+ public void testRequestScopeIsNotProxiable() {
+ InjecteeImpl injectee = new InjecteeImpl();
+ injectee.setInjecteeClass(TestRequestScope.class);
+ injectee.setParentClassScope(RequestScoped.class);
+
+ JerseyProxyResolver resolver = new JerseyProxyResolver();
+ assertFalse(resolver.isProxiable(injectee));
+ }
+
+ @Test
+ public void testApplicationIsNotProxiable() {
+ InjecteeImpl injectee = new InjecteeImpl();
+ injectee.setRequiredType(Application.class);
+
+ JerseyProxyResolver resolver = new JerseyProxyResolver();
+ assertFalse(resolver.isProxiable(injectee));
+ }
+
+ @Test
+ public void testProxyCreated() {
+ MyInjectionResolver injectionResolver = new MyInjectionResolver(new JaxrsProviders());
+ InjecteeImpl injectee = new InjecteeImpl();
+ injectee.setRequiredType(Providers.class);
+ injectee.setParent(FIELDS[0]);
+
+ JerseyProxyResolver resolver = new JerseyProxyResolver();
+ Object proxy = resolver.proxy(injectee, injectionResolver);
+ assertTrue(proxy.getClass().getName().contains("Proxy"));
+ }
+
+ @Test
+ public void testProxyCached() {
+ MyInjectionResolver injectionResolver = new MyInjectionResolver(new JaxrsProviders());
+ InjecteeImpl injectee1 = new InjecteeImpl();
+ injectee1.setRequiredType(Providers.class);
+ injectee1.setParent(FIELDS[0]);
+
+ InjecteeImpl injectee2 = new InjecteeImpl();
+ injectee2.setRequiredType(Providers.class);
+ injectee2.setParent(FIELDS[1]);
+
+ JerseyProxyResolver resolver = new JerseyProxyResolver();
+ Object proxy1 = resolver.proxy(injectee1, injectionResolver);
+ Object proxy2 = resolver.proxy(injectee2, injectionResolver);
+ assertSame(proxy1.getClass(), proxy2.getClass());
+ }
+
+ @Test
+ public void testProxyCacheNotMismatched() {
+ MyInjectionResolver injectionResolver1 = new MyInjectionResolver(new JaxrsProviders());
+ InjecteeImpl injectee1 = new InjecteeImpl();
+ injectee1.setRequiredType(Providers.class);
+ injectee1.setParent(FIELDS[0]);
+
+ MyInjectionResolver injectionResolver2 = new MyInjectionResolver(new ArrayList<>());
+ InjecteeImpl injectee2 = new InjecteeImpl();
+ injectee2.setRequiredType(List.class);
+ injectee2.setParent(FIELDS[1]);
+
+ JerseyProxyResolver resolver = new JerseyProxyResolver();
+ Object proxy1 = resolver.proxy(injectee1, injectionResolver1);
+ Object proxy2 = resolver.proxy(injectee2, injectionResolver2);
+ assertNotSame(proxy1.getClass(), proxy2.getClass());
+ }
+
+ private static class StubForFields {
+ private Object field1;
+ private Object field2;
+ }
+
+ private static class MyInjectionResolver implements InjectionResolver {
+
+ private final Object instance;
+
+ private MyInjectionResolver(Object instance) {
+ this.instance = instance;
+ }
+
+ @Override
+ public Object resolve(Injectee injectee) {
+ return instance;
+ }
+
+ @Override
+ public boolean isConstructorParameterIndicator() {
+ return true;
+ }
+
+ @Override
+ public boolean isMethodParameterIndicator() {
+ return false;
+ }
+
+ @Override
+ public Class getAnnotation() {
+ return Context.class;
+ }
+ }
+
+ private static class TestNonAnnotatedRequestScope {
+ }
+
+ @RequestScoped
+ private static class TestRequestScope {
+ }
+
+ @Singleton
+ private static class TestSingleton {
+ }
+
+ @ApplicationScoped
+ private static class TestApplicationScope {
+ }
+}
diff --git a/incubator/cdi-inject-weld/src/test/java/org/glassfish/jersey/inject/weld/internal/managed/BindingTestHelper.java b/incubator/cdi-inject-weld/src/test/java/org/glassfish/jersey/inject/weld/internal/managed/BindingTestHelper.java
new file mode 100644
index 0000000..f6184eb
--- /dev/null
+++ b/incubator/cdi-inject-weld/src/test/java/org/glassfish/jersey/inject/weld/internal/managed/BindingTestHelper.java
@@ -0,0 +1,58 @@
+/*
+ * Copyright (c) 2021 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.inject.weld.internal.managed;
+
+import org.glassfish.jersey.internal.inject.AbstractBinder;
+import org.glassfish.jersey.internal.inject.InjectionManager;
+import org.glassfish.jersey.internal.inject.Injections;
+
+import java.util.function.Consumer;
+
+/**
+ * Helper class to minimize the code in tested classes.
+ *
+ * @author Petr Bouda
+ */
+class BindingTestHelper {
+
+ /**
+ * Accepts the provided consumer to created and register the binder.
+ *
+ * @param injectionManager injection manager which accepts the consumer.
+ * @param bindConsumer consumer to populate a binder.
+ */
+ static void bind(InjectionManager injectionManager, Consumer<AbstractBinder> bindConsumer) {
+ AbstractBinder binder = new AbstractBinder() {
+ @Override
+ protected void configure() {
+ bindConsumer.accept(this);
+ }
+ };
+
+ injectionManager.register(binder);
+ // injectionManager.completeRegistration();
+ }
+
+ /**
+ * Creates a new {@link InjectionManager}.
+ *
+ * @return newly created {@code InjectionManager}.
+ */
+ static InjectionManager createInjectionManager() {
+ return Injections.createInjectionManager();
+ }
+}
diff --git a/incubator/cdi-inject-weld/src/test/java/org/glassfish/jersey/inject/weld/internal/managed/ClientInstanceInjectionTest.java b/incubator/cdi-inject-weld/src/test/java/org/glassfish/jersey/inject/weld/internal/managed/ClientInstanceInjectionTest.java
new file mode 100644
index 0000000..37ec79f
--- /dev/null
+++ b/incubator/cdi-inject-weld/src/test/java/org/glassfish/jersey/inject/weld/internal/managed/ClientInstanceInjectionTest.java
@@ -0,0 +1,226 @@
+/*
+ * Copyright (c) 2021 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.inject.weld.internal.managed;
+
+import javax.enterprise.context.Dependent;
+import javax.enterprise.inject.Vetoed;
+import javax.inject.Inject;
+import javax.ws.rs.RuntimeType;
+
+import org.glassfish.jersey.inject.weld.managed.CdiInjectionManagerFactory;
+import org.glassfish.jersey.internal.inject.InjectionManager;
+import org.junit.Assert;
+import org.junit.Test;
+
+import java.util.concurrent.atomic.AtomicInteger;
+import java.util.function.Supplier;
+
+public class ClientInstanceInjectionTest extends TestParent {
+
+ @Test
+ public void testInject() {
+ InjectionManager clientInjectionManager1 = new CdiInjectionManagerFactory().create(null, RuntimeType.CLIENT);
+ InjectionManager clientInjectionManager2 = new CdiInjectionManagerFactory().create(null, RuntimeType.CLIENT);
+
+ BindingTestHelper.bind(injectionManager, binder -> {
+ binder.bind(new StringInjectable(5)).to(Injectable.class);
+ });
+
+ BindingTestHelper.bind(clientInjectionManager1, binder -> {
+ binder.bind(new StringInjectable(10)).to(Injectable.class);
+ });
+
+ BindingTestHelper.bind(clientInjectionManager2, binder -> {
+ binder.bind(new StringInjectable(15)).to(Injectable.class);
+ });
+
+ InjectedBean bean = injectionManager.getInstance(InjectedBean.class);
+ Assert.assertNotNull(bean);
+ Assert.assertEquals("6", bean.get());
+
+ InjectedBean bean1 = clientInjectionManager1.getInstance(InjectedBean.class);
+ Assert.assertNotNull(bean1);
+ Assert.assertEquals("11", bean1.get());
+
+ InjectedBean bean2 = clientInjectionManager2.getInstance(InjectedBean.class);
+ Assert.assertNotNull(bean2);
+ Assert.assertEquals("16", bean2.get());
+
+ injectionManager.shutdown();
+ clientInjectionManager1.shutdown();
+ clientInjectionManager2.shutdown();
+ }
+
+ @Vetoed
+ static class InjectedBean {
+ @Inject
+ private Injectable injectable;
+
+ public String get() {
+ return injectable.get();
+ }
+ }
+
+ static class StringInjectable extends AbstractStringInjectable implements Injectable {
+ StringInjectable(int i) {
+ super(i);
+ }
+ }
+
+ static interface Injectable {
+ String get();
+ }
+
+
+ @Test
+ public void testSupplierInject() {
+ InjectionManager clientInjectionManager1 = new CdiInjectionManagerFactory().create(null, RuntimeType.CLIENT);
+ InjectionManager clientInjectionManager2 = new CdiInjectionManagerFactory().create(null, RuntimeType.CLIENT);
+
+ BindingTestHelper.bind(injectionManager, binder -> {
+ binder.bindFactory(new StringInjectableSupplier2(5)).to(Injectable2.class);
+ });
+
+ BindingTestHelper.bind(clientInjectionManager1, binder -> {
+ binder.bindFactory(new StringInjectableSupplier2(10)).to(Injectable2.class);
+ });
+
+ BindingTestHelper.bind(clientInjectionManager2, binder -> {
+ binder.bindFactory(new StringInjectableSupplier2(15)).to(Injectable2.class);
+ });
+
+ InjectedSupplierBean bean = injectionManager.getInstance(InjectedSupplierBean.class);
+ Assert.assertNotNull(bean);
+ Assert.assertEquals("6", bean.get());
+
+ InjectedSupplierBean bean1 = clientInjectionManager1.getInstance(InjectedSupplierBean.class);
+ Assert.assertNotNull(bean1);
+ Assert.assertEquals("11", bean1.get());
+
+ InjectedSupplierBean bean2 = clientInjectionManager2.getInstance(InjectedSupplierBean.class);
+ Assert.assertNotNull(bean2);
+ Assert.assertEquals("16", bean2.get());
+ }
+
+ @Dependent
+ static class InjectedSupplierBean {
+ @Inject
+ private Supplier<Injectable2> injectable;
+
+ public String get() {
+ return injectable.get().get();
+ }
+ }
+
+ static class StringInjectableSupplier2 implements Supplier<Injectable2> {
+ private final int i;
+ StringInjectableSupplier2(int i) {
+ this.i = i;
+ }
+
+ @Override
+ public Injectable2 get() {
+ return new StringInjectable2(i);
+ }
+ }
+
+ private static class StringInjectable2 extends AbstractStringInjectable implements Injectable2 {
+
+ StringInjectable2(int value) {
+ super(value);
+ }
+ }
+
+ static interface Injectable2 {
+ String get();
+ }
+
+ abstract static class AbstractStringInjectable {
+ protected AtomicInteger atomicInteger = new AtomicInteger(0);
+
+ AbstractStringInjectable(int value) {
+ atomicInteger.set(value);
+ }
+
+ public String get() {
+ return String.valueOf(atomicInteger.incrementAndGet());
+ }
+ }
+
+ @Test
+ public void testSupplierClassBeanOnClientAndServer() {
+ InjectionManager clientInjectionManager = new CdiInjectionManagerFactory().create(null, RuntimeType.CLIENT);
+ BindingTestHelper.bind(injectionManager, binder -> {
+ binder.bindFactory(InjectableClientServerSupplierServer.class).to(InjectableClientServer.class);
+ });
+
+ BindingTestHelper.bind(clientInjectionManager, binder -> {
+ binder.bindFactory(InjectableClientServerSupplierClient.class).to(InjectableClientServer.class);
+ });
+
+ InjectedClientServerSupplierBean beanServer = injectionManager.getInstance(InjectedClientServerSupplierBean.class);
+ Assert.assertNotNull(beanServer);
+ Assert.assertEquals("SERVER", beanServer.get());
+
+ InjectedClientServerSupplierBean beanClient = clientInjectionManager.getInstance(InjectedClientServerSupplierBean.class);
+ Assert.assertNotNull(beanClient);
+ Assert.assertEquals("CLIENT", beanClient.get());
+ }
+
+ @Dependent
+ static class InjectedClientServerSupplierBean {
+ @Inject
+ private Supplier<InjectableClientServer> injectable;
+
+ public String get() {
+ return injectable.get().get();
+ }
+ }
+
+ static class InjectableClientServerSupplierServer implements Supplier<InjectableClientServer> {
+ @Override
+ public InjectableClientServer get() {
+ return new InjectableClientServerServer();
+ }
+ }
+
+ static class InjectableClientServerSupplierClient implements Supplier<InjectableClientServer> {
+ @Override
+ public InjectableClientServer get() {
+ return new InjectableClientServerClient();
+ }
+ }
+
+ private static class InjectableClientServerServer implements InjectableClientServer {
+
+ @Override
+ public String get() {
+ return "SERVER";
+ }
+ }
+
+ private static class InjectableClientServerClient implements InjectableClientServer {
+ @Override
+ public String get() {
+ return "CLIENT";
+ }
+ }
+
+ static interface InjectableClientServer {
+ String get();
+ }
+}
diff --git a/incubator/cdi-inject-weld/src/test/java/org/glassfish/jersey/inject/weld/internal/managed/Conversation.java b/incubator/cdi-inject-weld/src/test/java/org/glassfish/jersey/inject/weld/internal/managed/Conversation.java
new file mode 100644
index 0000000..d10dc81
--- /dev/null
+++ b/incubator/cdi-inject-weld/src/test/java/org/glassfish/jersey/inject/weld/internal/managed/Conversation.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2021 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.inject.weld.internal.managed;
+
+import java.util.function.Supplier;
+
+import javax.enterprise.inject.Vetoed;
+import javax.inject.Inject;
+
+/**
+ * @author Petr Bouda
+ */
+@Vetoed
+class Conversation {
+
+ @Inject
+ Greeting greeting;
+
+ @Inject
+ Supplier<Greeting> greetingSupplier;
+
+}
diff --git a/incubator/cdi-inject-weld/src/test/java/org/glassfish/jersey/inject/weld/internal/managed/CzechConversation.java b/incubator/cdi-inject-weld/src/test/java/org/glassfish/jersey/inject/weld/internal/managed/CzechConversation.java
new file mode 100644
index 0000000..b3a8594
--- /dev/null
+++ b/incubator/cdi-inject-weld/src/test/java/org/glassfish/jersey/inject/weld/internal/managed/CzechConversation.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2021 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.inject.weld.internal.managed;
+
+import java.util.function.Supplier;
+
+import javax.enterprise.inject.Vetoed;
+import javax.inject.Inject;
+
+/**
+ * @author Petr Bouda
+ */
+@Vetoed
+class CzechConversation {
+
+ @Inject
+ CzechGreeting greeting;
+
+ @Inject
+ Supplier<CzechGreeting> greetingSupplier;
+
+}
diff --git a/incubator/cdi-inject-weld/src/test/java/org/glassfish/jersey/inject/weld/internal/managed/CzechGreeting.java b/incubator/cdi-inject-weld/src/test/java/org/glassfish/jersey/inject/weld/internal/managed/CzechGreeting.java
new file mode 100644
index 0000000..a60f546
--- /dev/null
+++ b/incubator/cdi-inject-weld/src/test/java/org/glassfish/jersey/inject/weld/internal/managed/CzechGreeting.java
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2021 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.inject.weld.internal.managed;
+
+import javax.enterprise.inject.Vetoed;
+
+/**
+ * @author Petr Bouda
+ */
+@Vetoed
+public class CzechGreeting implements Greeting, Printable {
+
+ static final String GREETING = "Ahoj";
+
+ @Override
+ public String getGreeting() {
+ return GREETING + "#" + Thread.currentThread().getName();
+ }
+
+ @Override
+ public void print() {
+ System.out.println(GREETING);
+ }
+
+ @Override
+ public String toString() {
+ return "CzechGreeting";
+ }
+}
diff --git a/incubator/cdi-inject-weld/src/test/java/org/glassfish/jersey/inject/weld/internal/managed/DisposableSupplierTest.java b/incubator/cdi-inject-weld/src/test/java/org/glassfish/jersey/inject/weld/internal/managed/DisposableSupplierTest.java
new file mode 100644
index 0000000..4ba137b
--- /dev/null
+++ b/incubator/cdi-inject-weld/src/test/java/org/glassfish/jersey/inject/weld/internal/managed/DisposableSupplierTest.java
@@ -0,0 +1,595 @@
+/*
+ * Copyright (c) 2021 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.inject.weld.internal.managed;
+
+import java.lang.reflect.Type;
+import java.util.Objects;
+import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.concurrent.atomic.AtomicInteger;
+import java.util.concurrent.atomic.AtomicReference;
+import java.util.function.Supplier;
+
+import javax.enterprise.inject.Vetoed;
+import javax.inject.Inject;
+import javax.ws.rs.core.GenericType;
+
+import org.glassfish.jersey.inject.weld.internal.bean.BeanHelper;
+import org.glassfish.jersey.internal.inject.DisposableSupplier;
+import org.glassfish.jersey.process.internal.RequestScope;
+
+import org.junit.Before;
+import org.junit.Test;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNotSame;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertSame;
+
+/**
+ * Tests that {@link DisposableSupplier} is properly processed by {@link BeanHelper}.
+ *
+ * @author Petr Bouda
+ */
+@Vetoed
+public class DisposableSupplierTest extends TestParent {
+
+ private static final Type DISPOSABLE_SUPPLIER_CLASS_TYPE =
+ new GenericType<DisposableSupplier<StringForSupplierClass>>() {}.getType();
+ private static final Type DISPOSABLE_SUPPLIER_SINGLETON_CLASS_TYPE =
+ new GenericType<DisposableSupplier<StringForSupplierSingletonClass>>() {}.getType();
+ private static final Type DISPOSABLE_SUPPLIER_INSTANCE_TYPE =
+ new GenericType<DisposableSupplier<StringForSupplierInstance>>() {}.getType();
+ private static final Type PROXIABLE_DISPOSABLE_SUPPLIER_CLASS_TYPE =
+ new GenericType<DisposableSupplier<ProxiableHolderClass>>() {}.getType();
+
+ private static AtomicBoolean onlyOnceGuard = new AtomicBoolean(false);
+
+ @Before
+ public void bindInit() {
+ if (!onlyOnceGuard.getAndSet(true)) {
+ BindingTestHelper.bind(injectionManager, binder -> binder.bindFactory(new DisposableSupplierImpl())
+ .to(StringForSupplierInstance.class));
+ }
+ }
+
+ @Test
+ public void testBindSingletonClassDisposableSupplier() {
+// BindingTestHelper.bind(injectionManager, binder -> binder.bindFactory(DisposableSupplierImpl.class, Singleton.class)
+// .to(StringForSupplierSingletonClass.class));
+
+ Object supplier = injectionManager.getInstance(new GenericType<Supplier<StringForSupplierSingletonClass>>() {}.getType());
+ Object disposableSupplier = injectionManager.getInstance(DISPOSABLE_SUPPLIER_SINGLETON_CLASS_TYPE);
+ assertNotNull(supplier);
+ assertNotNull(disposableSupplier);
+ assertSame(supplier, disposableSupplier);
+ }
+
+ @Test
+ public void testBindPerLookupClassDisposableSupplier() {
+// BindingTestHelper.bind(injectionManager, binder -> binder.bindFactory(DisposableSupplierImpl.class)
+// .to(StringForSupplierClass.class));
+
+ Object supplier = injectionManager.getInstance(new GenericType<Supplier<StringForSupplierClass>>() {}.getType());
+ Object disposableSupplier = injectionManager.getInstance(DISPOSABLE_SUPPLIER_CLASS_TYPE);
+ assertNotNull(supplier);
+ assertNotNull(disposableSupplier);
+ assertNotSame(supplier, disposableSupplier);
+ }
+
+ @Test
+ public void testBindInstanceDisposableSupplier() {
+// BindingTestHelper.bind(injectionManager, binder -> binder.bindFactory(new DisposableSupplierImpl())
+// .to(StringForSupplierInstance.class));
+
+ Object supplier = injectionManager.getInstance(new GenericType<Supplier<StringForSupplierInstance>>() {}.getType());
+ Object disposableSupplier = injectionManager.getInstance(DISPOSABLE_SUPPLIER_INSTANCE_TYPE);
+ assertNotNull(supplier);
+ assertNotNull(disposableSupplier);
+ assertSame(supplier, disposableSupplier);
+ }
+
+ @Test
+ public void testNotBindClassDisposableSupplier() {
+// BindingTestHelper.bind(injectionManager, binder -> binder.bindFactory(SupplierGreeting.class).to(GreetingsClass.class));
+ assertNull(injectionManager.getInstance(new GenericType<DisposableSupplier<GreetingsClass>>() {}.getType()));
+ }
+
+ @Test
+ public void testNotBindInstanceDisposableSupplier() {
+// BindingTestHelper.bind(injectionManager,
+// binder -> binder.bindFactory(new SupplierGreeting()).to(GreetingsInstance.class));
+ assertNull(injectionManager.getInstance(new GenericType<DisposableSupplier<GreetingsInstance>>() {}.getType()));
+ }
+
+ @Test
+ public void testOnlyIncrementSingletonSupplier() {
+// BindingTestHelper.bind(injectionManager, binder -> binder.bindFactory(DisposableSupplierImpl.class, Singleton.class)
+// .to(StringForSupplierSingletonClass.class));
+
+ Object instance1 = injectionManager.getInstance(DISPOSABLE_SUPPLIER_SINGLETON_CLASS_TYPE);
+ assertEquals("1", ((DisposableSupplier<?>) instance1).get());
+ Object instance2 = injectionManager.getInstance(DISPOSABLE_SUPPLIER_SINGLETON_CLASS_TYPE);
+ assertEquals("2", ((DisposableSupplier<?>) instance2).get());
+ Object instance3 = injectionManager.getInstance(DISPOSABLE_SUPPLIER_SINGLETON_CLASS_TYPE);
+ assertEquals("3", ((DisposableSupplier<?>) instance3).get());
+ dispose(instance1, instance2, instance3);
+ }
+
+ @Test
+ public void testOnlyIncrementInstanceSupplier() {
+// BindingTestHelper.bind(injectionManager, binder -> binder.bindFactory(new DisposableSupplierImpl())
+// .to(StringForSupplierInstance.class));
+
+ Object instance1 = injectionManager.getInstance(DISPOSABLE_SUPPLIER_INSTANCE_TYPE);
+ assertEquals("1", ((DisposableSupplier<?>) instance1).get());
+ Object instance2 = injectionManager.getInstance(DISPOSABLE_SUPPLIER_INSTANCE_TYPE);
+ assertEquals("2", ((DisposableSupplier<?>) instance2).get());
+ Object instance3 = injectionManager.getInstance(DISPOSABLE_SUPPLIER_INSTANCE_TYPE);
+ assertEquals("3", ((DisposableSupplier<?>) instance3).get());
+ dispose(instance1, instance2, instance3);
+ }
+
+ @Test
+ public void testOnlyIncrementPerLookupSupplier() {
+// BindingTestHelper.bind(injectionManager, binder -> binder.bindFactory(DisposableSupplierImpl.class)
+// .to(StringForSupplierClass.class));
+
+ Object instance1 = injectionManager.getInstance(DISPOSABLE_SUPPLIER_CLASS_TYPE);
+ assertEquals("1", ((DisposableSupplier<?>) instance1).get());
+ Object instance2 = injectionManager.getInstance(DISPOSABLE_SUPPLIER_CLASS_TYPE);
+ assertEquals("1", ((DisposableSupplier<?>) instance2).get());
+ Object instance3 = injectionManager.getInstance(DISPOSABLE_SUPPLIER_CLASS_TYPE);
+ assertEquals("1", ((DisposableSupplier<?>) instance3).get());
+ dispose(instance1, instance2, instance3);
+ }
+
+ @Test
+ public void testOnlyIncrementSingletonInstances() {
+// BindingTestHelper.bind(injectionManager, binder -> binder.bindFactory(DisposableSupplierImpl.class, Singleton.class)
+// .to(StringForSupplierSingletonClass.class));
+
+ Object instance1 = injectionManager.getInstance(StringForSupplierSingletonClass.class);
+ assertEquals("1", instance1);
+ Object instance2 = injectionManager.getInstance(StringForSupplierSingletonClass.class);
+ assertEquals("2", instance2);
+ Object instance3 = injectionManager.getInstance(StringForSupplierSingletonClass.class);
+ assertEquals("3", instance3);
+ Object o = injectionManager.getInstance(
+ new GenericType<DisposableSupplier<StringForSupplierSingletonClass>>() {}.getType());
+ dispose(o, o, o);
+ }
+
+ @Test
+ public void testOnlyIncrementInstanceInstance() {
+// BindingTestHelper.bind(injectionManager, binder -> binder.bindFactory(new DisposableSupplierImpl())
+// .to(StringForSupplierInstance.class));
+
+ Object instance1 = injectionManager.getInstance(StringForSupplierInstance.class);
+ assertEquals("1", instance1);
+ Object instance2 = injectionManager.getInstance(StringForSupplierInstance.class);
+ assertEquals("2", instance2);
+ Object instance3 = injectionManager.getInstance(StringForSupplierInstance.class);
+ assertEquals("3", instance3);
+ Object o = injectionManager.getInstance(new GenericType<DisposableSupplier<StringForSupplierInstance>>() {}.getType());
+ dispose(o, o, o);
+ }
+
+ @Test
+ public void testDisposeSingletonSupplier() {
+// BindingTestHelper.bind(injectionManager, binder -> binder.bindFactory(DisposableSupplierImpl.class, Singleton.class)
+// .to(StringForSupplierSingletonClass.class));
+
+ // 1-1
+ DisposableSupplier<StringForSupplierSingletonClass> supplier1 =
+ injectionManager.getInstance(DISPOSABLE_SUPPLIER_SINGLETON_CLASS_TYPE);
+ CharSequence instance1 = supplier1.get();
+ // 2-2
+ DisposableSupplier<StringForSupplierSingletonClass> supplier2 =
+ injectionManager.getInstance(DISPOSABLE_SUPPLIER_SINGLETON_CLASS_TYPE);
+ CharSequence instance2 = supplier2.get();
+ // 3-3
+ DisposableSupplier<StringForSupplierSingletonClass> supplier3 =
+ injectionManager.getInstance(DISPOSABLE_SUPPLIER_SINGLETON_CLASS_TYPE);
+ supplier3.get();
+ // 2-2
+ supplier1.dispose(null);
+ // 1-1
+ supplier2.dispose(null);
+ // 2-2
+ Supplier<StringForSupplierSingletonClass> supplier4 = injectionManager.getInstance(
+ DISPOSABLE_SUPPLIER_SINGLETON_CLASS_TYPE);
+ CharSequence result = supplier4.get();
+ assertEquals("2", result);
+ dispose(supplier3, supplier4);
+ }
+
+ @Test
+ public void testDisposePerLookupSupplier() {
+// BindingTestHelper.bind(injectionManager, binder -> binder.bindFactory(DisposableSupplierImpl.class)
+// .to(StringForSupplierClass.class));
+
+ // 1
+ DisposableSupplier<StringForSupplierClass> supplier1 =
+ injectionManager.getInstance(DISPOSABLE_SUPPLIER_CLASS_TYPE);
+ CharSequence instance1 = supplier1.get();
+ // 1
+ DisposableSupplier<StringForSupplierClass> supplier2 =
+ injectionManager.getInstance(DISPOSABLE_SUPPLIER_CLASS_TYPE);
+ CharSequence instance2 = supplier2.get();
+ // 1
+ DisposableSupplier<StringForSupplierClass> supplier3 =
+ injectionManager.getInstance(DISPOSABLE_SUPPLIER_CLASS_TYPE);
+ supplier3.get();
+ // 0
+ supplier1.dispose(null);
+ // 0
+ supplier2.dispose(null);
+ // 1
+ Supplier<StringForSupplierClass> supplier4 = injectionManager.getInstance(DISPOSABLE_SUPPLIER_CLASS_TYPE);
+ CharSequence result = supplier4.get();
+ assertEquals("1", result);
+ dispose(supplier3, supplier4);
+ }
+
+ @Test
+ public void testDisposeSingletonSupplierRequestScopedInstance() {
+// BindingTestHelper.bind(injectionManager, binder -> {
+// binder.bindFactory(ProxiableDisposableSingletonSupplierImpl.class, Singleton.class)
+// .to(ProxiableHolderSingletonClass.class)
+// .in(RequestScoped.class);
+// });
+
+ RequestScope request = injectionManager.getInstance(RequestScope.class);
+ AtomicReference<Supplier<ProxiableHolderSingletonClass>> atomicSupplier = new AtomicReference<>();
+ request.runInScope(() -> {
+ // Save Singleton Supplier for later check that the instance was disposed.
+ Supplier<ProxiableHolderSingletonClass> supplier = injectionManager.getInstance(
+ new GenericType<DisposableSupplier<ProxiableHolderSingletonClass>>() {}.getType());
+ atomicSupplier.set(supplier);
+
+ // All instances should be the same because they are request scoped.
+ ProxiableHolderSingletonClass instance1 = injectionManager.getInstance(ProxiableHolderSingletonClass.class);
+ assertEquals("1", instance1.getValue());
+ ProxiableHolderSingletonClass instance2 = injectionManager.getInstance(ProxiableHolderSingletonClass.class);
+ assertEquals("1", instance2.getValue());
+ });
+
+ Supplier<ProxiableHolderSingletonClass> cleanedSupplier = atomicSupplier.get();
+ // Next should be 1-1
+ assertEquals("1", cleanedSupplier.get().getValue());
+ }
+
+ /**
+ * Tests that object created in request scope is disposing at the time of ending the scope.
+ */
+ @Test
+ public void testDisposePerLookupSupplierRequestScopedInstance() {
+// BindingTestHelper.bind(injectionManager, binder -> {
+// binder.bindFactory(ProxiableDisposableSupplierImpl.class)
+// .to(ProxiableHolderClass.class)
+// .in(RequestScoped.class);
+// });
+
+ RequestScope request = injectionManager.getInstance(RequestScope.class);
+ AtomicReference<Supplier<ProxiableHolderClass>> atomicSupplier = new AtomicReference<>();
+ request.runInScope(() -> {
+ // Save Singleton Supplier for later check that the instance was disposed.
+ Supplier<ProxiableHolderClass> supplier = injectionManager.getInstance(PROXIABLE_DISPOSABLE_SUPPLIER_CLASS_TYPE);
+ atomicSupplier.set(supplier);
+
+ // All instances should be the same because they are request scoped.
+ ProxiableHolderClass instance1 = injectionManager.getInstance(ProxiableHolderClass.class);
+ assertEquals("1", instance1.getValue());
+ ProxiableHolderClass instance2 = injectionManager.getInstance(ProxiableHolderClass.class);
+ assertEquals("1", instance2.getValue());
+ });
+
+ Supplier<ProxiableHolderClass> cleanedSupplier = atomicSupplier.get();
+ // Next should be 1
+ assertEquals("1", cleanedSupplier.get().getValue());
+ }
+
+ /**
+ * Tests that inherited request scoped is also cleaned by disposing the objects.
+ */
+ @Test
+ public void testDisposeSingletonSupplierMultiRequestScoped() {
+// BindingTestHelper.bind(injectionManager, binder -> {
+// binder.bindFactory(ProxiableDisposableSupplierImpl.class)
+// .to(ProxiableHolderClass.class)
+// .in(RequestScoped.class);
+// });
+
+ RequestScope request = injectionManager.getInstance(RequestScope.class);
+ AtomicReference<Supplier<ProxiableHolderClass>> firstSupplier = new AtomicReference<>();
+ AtomicReference<Supplier<ProxiableHolderClass>> secondSupplier = new AtomicReference<>();
+
+ request.runInScope(() -> {
+ Supplier<ProxiableHolderClass> supplier1 = injectionManager.getInstance(PROXIABLE_DISPOSABLE_SUPPLIER_CLASS_TYPE);
+ firstSupplier.set(supplier1);
+
+ ProxiableHolderClass instance1 = injectionManager.getInstance(ProxiableHolderClass.class);
+ assertEquals("1", instance1.getValue());
+
+ request.runInScope(() -> {
+ // Save Singleton Supplier for later check that the instance was disposed.
+ Supplier<ProxiableHolderClass> supplier2 = injectionManager.getInstance(PROXIABLE_DISPOSABLE_SUPPLIER_CLASS_TYPE);
+ secondSupplier.set(supplier2);
+
+ ProxiableHolderClass instance2 = injectionManager.getInstance(ProxiableHolderClass.class);
+ // 1-2 because the same static class is used in inherited runInScope
+ assertEquals("1", instance2.getValue());
+ });
+ });
+
+ Supplier<ProxiableHolderClass> cleanedSupplier1 = firstSupplier.get();
+ Supplier<ProxiableHolderClass> cleanedSupplier2 = secondSupplier.get();
+ // Next should be 1-1
+ assertEquals("1", cleanedSupplier1.get().getValue());
+ // 1-2 because the same static class is used but the instance is cleaned.
+ assertEquals("1", cleanedSupplier2.get().getValue());
+ }
+
+ /**
+ * PerLookup fields are not disposed therefore they should never be used as a DisposedSupplier because the field stay in
+ * {@link org.glassfish.jersey.inject.weld.bean.SupplierClassBean} forever.
+ */
+ @Test
+ public void testDisposeComposedObjectWithPerLookupFields() {
+// BindingTestHelper.bind(injectionManager, binder -> {
+// binder.bindFactory(DisposableSupplierForComposedImpl.class, Singleton.class)
+// .to(StringForComposed.class);
+//
+// binder.bindAsContract(ComposedObject.class)
+// .in(RequestScoped.class);
+// });
+
+ RequestScope request = injectionManager.getInstance(RequestScope.class);
+ AtomicReference<Supplier<StringForComposed>> atomicSupplier = new AtomicReference<>();
+ request.runInScope(() -> {
+ // Save Singleton Supplier for later check that the instance was disposed.
+ Supplier<StringForComposed> supplier = injectionManager.getInstance(
+ new GenericType<DisposableSupplier<StringForComposed>>() {}.getType());
+ atomicSupplier.set(supplier);
+
+ // All instances should be the same because they are request scoped.
+ ComposedObject instance = injectionManager.getInstance(ComposedObject.class);
+ assertEquals("1", instance.getFirst().toString());
+ assertEquals("2", instance.getSecond().toString());
+ assertEquals("3", instance.getThird().toString());
+ });
+
+ Supplier<StringForComposed> cleanedSupplier = atomicSupplier.get();
+ // Next should be 1 - all instances are disposed and decremented back
+ assertEquals("1", cleanedSupplier.get().toString());
+ }
+
+ private void dispose(Object... objects) {
+ for (Object object : objects) {
+ if (DisposableSupplier.class.isInstance(object)) {
+ ((DisposableSupplier) object).dispose(null);
+ }
+ }
+ }
+
+ @Vetoed
+ static class ComposedObject {
+
+ @Inject
+ StringForComposed first;
+
+ @Inject
+ StringForComposed second;
+
+ @Inject
+ StringForComposed third;
+
+ public StringForComposed getFirst() {
+ return first;
+ }
+
+ public StringForComposed getSecond() {
+ return second;
+ }
+
+ public StringForComposed getThird() {
+ return third;
+ }
+ }
+
+ @Vetoed
+ static class DisposableSupplierForComposedImpl implements DisposableSupplier<StringForComposed> {
+ private final AtomicInteger counter = new AtomicInteger();
+
+ @Override
+ public StringForComposed get() {
+ // Create a new string - don't share the instances in the string pool.
+ return new StringForComposed(counter.incrementAndGet() + "");
+ }
+
+ @Override
+ public void dispose(final StringForComposed instance) {
+ counter.decrementAndGet();
+ }
+ }
+
+ @Vetoed
+ static class DisposableSupplierImpl implements DisposableSupplier<String> {
+ private final AtomicInteger counter = new AtomicInteger();
+
+ @Override
+ public String get() {
+ // Create a new string - don't share the instances in the string pool.
+ return new String(counter.incrementAndGet() + "");
+ }
+
+ @Override
+ public void dispose(final String instance) {
+ counter.decrementAndGet();
+ }
+ }
+
+ @Vetoed
+ static class ProxiableDisposableSupplierImpl implements DisposableSupplier<AbstractProxiableHolder> {
+ private final AtomicInteger counter = new AtomicInteger();
+
+ @Override
+ public AbstractProxiableHolder get() {
+ // Create a new string - don't share the instances in the string pool.
+ return new ProxiableHolderClass(counter.incrementAndGet() + "");
+ }
+
+ @Override
+ public void dispose(AbstractProxiableHolder instance) {
+ counter.decrementAndGet();
+ }
+ }
+
+ @Vetoed
+ static class ProxiableDisposableSingletonSupplierImpl implements DisposableSupplier<AbstractProxiableHolder> {
+ private final AtomicInteger counter = new AtomicInteger();
+
+ @Override
+ public AbstractProxiableHolder get() {
+ // Create a new string - don't share the instances in the string pool.
+ return new ProxiableHolderSingletonClass(counter.incrementAndGet() + "");
+ }
+
+ @Override
+ public void dispose(AbstractProxiableHolder instance) {
+ counter.decrementAndGet();
+ }
+ }
+
+ @Vetoed
+ static class ProxiableHolderSingletonClass extends AbstractProxiableHolder {
+ public ProxiableHolderSingletonClass(String value) {
+ super(value);
+ }
+ }
+
+ @Vetoed
+ static class ProxiableHolderClass extends AbstractProxiableHolder {
+ public ProxiableHolderClass(String value) {
+ super(value);
+ }
+ }
+
+ @Vetoed
+ abstract static class AbstractProxiableHolder {
+ private String value;
+
+ public AbstractProxiableHolder(String value) {
+ this.value = value;
+ }
+
+ public String getValue() {
+ return value;
+ }
+ }
+
+
+ @Vetoed
+ static final class GreetingsInstance extends ExtendableString {
+ public GreetingsInstance(CharSequence inner) {
+ super(inner);
+ }
+ }
+
+ @Vetoed
+ static final class GreetingsClass extends ExtendableString {
+ public GreetingsClass(CharSequence inner) {
+ super(inner);
+ }
+ }
+
+ @Vetoed
+ static final class StringForComposed extends ExtendableString {
+ public StringForComposed(CharSequence inner) {
+ super(inner);
+ }
+ }
+
+ @Vetoed
+ static final class StringForSupplierSingletonClass extends ExtendableString {
+ public StringForSupplierSingletonClass(CharSequence inner) {
+ super(inner);
+ }
+ }
+
+ @Vetoed
+ static final class StringForSupplierClass extends ExtendableString {
+ public StringForSupplierClass(CharSequence inner) {
+ super(inner);
+ }
+ }
+
+ @Vetoed
+ static final class StringForSupplierInstance extends ExtendableString {
+ public StringForSupplierInstance(CharSequence inner) {
+ super(inner);
+ }
+ }
+
+ static class ExtendableString implements CharSequence, Comparable<ExtendableString> {
+
+ private final CharSequence inner;
+
+ protected ExtendableString(CharSequence inner) {
+ this.inner = inner;
+ }
+
+ @Override
+ public int length() {
+ return inner.length();
+ }
+
+ @Override
+ public char charAt(int index) {
+ return inner.charAt(index);
+ }
+
+ @Override
+ public CharSequence subSequence(int start, int end) {
+ return inner.subSequence(start, end);
+ }
+
+ @Override
+ public String toString() {
+ return inner.toString();
+ }
+
+ @Override
+ public int compareTo(ExtendableString o) {
+ if (this == o) return 0;
+ if (o == null) return -1;
+ return Objects.compare(inner.toString(), o.toString(), String.CASE_INSENSITIVE_ORDER);
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (o == null) return false;
+ return Objects.equals(inner.toString(), inner.toString());
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(inner);
+ }
+ }
+}
diff --git a/incubator/cdi-inject-weld/src/test/java/org/glassfish/jersey/inject/weld/internal/managed/EnglishGreeting.java b/incubator/cdi-inject-weld/src/test/java/org/glassfish/jersey/inject/weld/internal/managed/EnglishGreeting.java
new file mode 100644
index 0000000..767b117
--- /dev/null
+++ b/incubator/cdi-inject-weld/src/test/java/org/glassfish/jersey/inject/weld/internal/managed/EnglishGreeting.java
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2021 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.inject.weld.internal.managed;
+
+import javax.enterprise.inject.Vetoed;
+
+/**
+ * @author Petr Bouda
+ */
+@Vetoed
+public class EnglishGreeting implements Greeting, Printable {
+
+ static final String GREETING = "Hello";
+
+ @Override
+ public String getGreeting() {
+ return GREETING + "#" + Thread.currentThread().getName();
+ }
+
+ @Override
+ public void print() {
+ System.out.println(GREETING);
+ }
+
+ @Override
+ public String toString() {
+ return "EnglishGreeting";
+ }
+}
diff --git a/incubator/cdi-inject-weld/src/test/java/org/glassfish/jersey/inject/weld/internal/managed/Greeting.java b/incubator/cdi-inject-weld/src/test/java/org/glassfish/jersey/inject/weld/internal/managed/Greeting.java
new file mode 100644
index 0000000..5f0551e
--- /dev/null
+++ b/incubator/cdi-inject-weld/src/test/java/org/glassfish/jersey/inject/weld/internal/managed/Greeting.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2021 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.inject.weld.internal.managed;
+
+/**
+ * @author Petr Bouda
+ */
+@FunctionalInterface
+public interface Greeting {
+
+ /**
+ * Returns greeting in a specific language.
+ *
+ * @return type of the greeting.
+ */
+ String getGreeting();
+
+}
diff --git a/incubator/cdi-inject-weld/src/test/java/org/glassfish/jersey/inject/weld/internal/managed/InjectionManagerTest.java b/incubator/cdi-inject-weld/src/test/java/org/glassfish/jersey/inject/weld/internal/managed/InjectionManagerTest.java
new file mode 100644
index 0000000..6cf1053
--- /dev/null
+++ b/incubator/cdi-inject-weld/src/test/java/org/glassfish/jersey/inject/weld/internal/managed/InjectionManagerTest.java
@@ -0,0 +1,56 @@
+/*
+ * Copyright (c) 2021 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.inject.weld.internal.managed;
+
+import javax.enterprise.context.Dependent;
+import javax.inject.Inject;
+import javax.ws.rs.RuntimeType;
+
+import org.glassfish.jersey.inject.weld.managed.CdiInjectionManagerFactory;
+import org.glassfish.jersey.internal.inject.InjectionManager;
+import org.junit.Assert;
+import org.junit.Test;
+
+public class InjectionManagerTest extends TestParent {
+
+ @Test
+ public void injectionManagerTest() {
+ injectionManager.completeRegistration();
+ final InjectionManagerInjectedBean bean = injectionManager.getInstance(InjectionManagerInjectedBean.class);
+ Assert.assertNotNull(bean);
+ InjectionManager got = bean.getInjectionManager();
+ Assert.assertEquals(injectionManager, got);
+
+ final InjectionManager clientInjectionManager = new CdiInjectionManagerFactory().create(null, RuntimeType.CLIENT);
+ clientInjectionManager.completeRegistration();
+ final InjectionManagerInjectedBean clientBean = clientInjectionManager.getInstance(InjectionManagerInjectedBean.class);
+ Assert.assertNotNull(clientBean);
+ InjectionManager gotClient = clientBean.getInjectionManager();
+ Assert.assertEquals(clientInjectionManager, gotClient);
+ }
+
+ @Dependent
+ public static class InjectionManagerInjectedBean {
+ @Inject
+ InjectionManager injectionManager;
+
+ InjectionManager getInjectionManager() {
+ return injectionManager;
+ }
+ }
+
+}
diff --git a/incubator/cdi-inject-weld/src/test/java/org/glassfish/jersey/inject/weld/internal/managed/MyVetoedLongSupplier.java b/incubator/cdi-inject-weld/src/test/java/org/glassfish/jersey/inject/weld/internal/managed/MyVetoedLongSupplier.java
new file mode 100644
index 0000000..fe1f720
--- /dev/null
+++ b/incubator/cdi-inject-weld/src/test/java/org/glassfish/jersey/inject/weld/internal/managed/MyVetoedLongSupplier.java
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2021 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.inject.weld.internal.managed;
+
+import java.util.concurrent.atomic.AtomicLong;
+import java.util.function.Supplier;
+
+import javax.enterprise.inject.Vetoed;
+
+@Vetoed
+public class MyVetoedLongSupplier implements Supplier<Long> {
+
+ private final AtomicLong counter = new AtomicLong();
+
+ @Override
+ public Long get() {
+ return counter.incrementAndGet();
+ }
+}
diff --git a/incubator/cdi-inject-weld/src/test/java/org/glassfish/jersey/inject/weld/internal/managed/Printable.java b/incubator/cdi-inject-weld/src/test/java/org/glassfish/jersey/inject/weld/internal/managed/Printable.java
new file mode 100644
index 0000000..4307ea8
--- /dev/null
+++ b/incubator/cdi-inject-weld/src/test/java/org/glassfish/jersey/inject/weld/internal/managed/Printable.java
@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) 2021 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.inject.weld.internal.managed;
+
+/**
+ * @author Petr Bouda
+ */
+@FunctionalInterface
+public interface Printable {
+
+ void print();
+
+}
diff --git a/incubator/cdi-inject-weld/src/test/java/org/glassfish/jersey/inject/weld/internal/managed/PrintableConversation.java b/incubator/cdi-inject-weld/src/test/java/org/glassfish/jersey/inject/weld/internal/managed/PrintableConversation.java
new file mode 100644
index 0000000..f507e55
--- /dev/null
+++ b/incubator/cdi-inject-weld/src/test/java/org/glassfish/jersey/inject/weld/internal/managed/PrintableConversation.java
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 2021 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.inject.weld.internal.managed;
+
+import java.util.function.Supplier;
+
+import javax.enterprise.inject.Vetoed;
+import javax.inject.Inject;
+
+/**
+ * @author Petr Bouda
+ */
+@Vetoed
+class PrintableConversation {
+
+ @Inject
+ Greeting greeting;
+
+ @Inject
+ Supplier<Greeting> greetingSupplier;
+
+ @Inject
+ Printable printable;
+
+ @Inject
+ Supplier<Printable> printableSupplier;
+
+}
diff --git a/incubator/cdi-inject-weld/src/test/java/org/glassfish/jersey/inject/weld/internal/managed/ProviderInjectionTest.java b/incubator/cdi-inject-weld/src/test/java/org/glassfish/jersey/inject/weld/internal/managed/ProviderInjectionTest.java
new file mode 100644
index 0000000..3fe20cf
--- /dev/null
+++ b/incubator/cdi-inject-weld/src/test/java/org/glassfish/jersey/inject/weld/internal/managed/ProviderInjectionTest.java
@@ -0,0 +1,232 @@
+/*
+ * Copyright (c) 2021 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.inject.weld.internal.managed;
+
+import javax.enterprise.event.Observes;
+import javax.enterprise.inject.Vetoed;
+import javax.enterprise.inject.se.SeContainerInitializer;
+import javax.enterprise.inject.spi.BeanManager;
+import javax.enterprise.inject.spi.BeforeBeanDiscovery;
+import javax.enterprise.inject.spi.Extension;
+import javax.inject.Inject;
+import javax.inject.Provider;
+import javax.ws.rs.core.Context;
+
+import org.glassfish.jersey.internal.inject.AbstractBinder;
+
+import org.hamcrest.core.StringStartsWith;
+import org.junit.Assert;
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+import java.util.function.Supplier;
+
+import static org.junit.Assert.assertThat;
+
+public class ProviderInjectionTest extends TestParent {
+
+ @BeforeClass
+ public static void setup() {
+ SeContainerInitializer containerInitializer = SeContainerInitializer.newInstance();
+ containerInitializer.addExtensions(new ProviderInjectionTestExtension());
+ container = containerInitializer.initialize();
+ }
+
+
+ @Test
+ public void testProviderInject() {
+// BindingTestHelper.bind(injectionManager, binder -> {
+// binder.bind(CzechGreeting.class).to(Greeting.class);
+// binder.bindAsContract(ProviderInject.class);
+// });
+
+ Greeting greeting = injectionManager.getInstance(Greeting.class);
+ Assert.assertNotNull(greeting);
+
+ ProviderInject instance = injectionManager.getInstance(ProviderInject.class);
+ assertThat(instance.greeting.get().getGreeting(), StringStartsWith.startsWith(CzechGreeting.GREETING));
+ }
+
+ @Test
+ public void testProviderContext() {
+// BindingTestHelper.bind(injectionManager, binder -> {
+// binder.bind(CzechGreeting.class).to(Greeting.class);
+// binder.bindAsContract(ProviderContext.class);
+// });
+
+ ProviderContext instance = injectionManager.getInstance(ProviderContext.class);
+ assertThat(instance.greeting.get().getGreeting(), StringStartsWith.startsWith(CzechGreeting.GREETING));
+ }
+
+ @Test
+ public void testProviderFactoryInject() {
+// BindingTestHelper.bind(injectionManager, binder -> {
+// binder.bindFactory(SupplierGreeting.class).to(Greeting2.class);
+// binder.bindAsContract(ProviderInject2.class);
+// });
+
+ ProviderInject2 conversation = injectionManager.getInstance(ProviderInject2.class);
+ assertThat(conversation.greeting.get().getGreeting(), StringStartsWith.startsWith(CzechGreeting.GREETING));
+ }
+
+
+ @Test
+ public void testProviderFactoryContext() {
+// BindingTestHelper.bind(injectionManager, binder -> {
+// binder.bindFactory(SupplierGreeting.class).to(Greeting2.class);
+// binder.bindAsContract(ProviderContext2.class);
+// });
+
+ ProviderContext2 conversation = injectionManager.getInstance(ProviderContext2.class);
+ assertThat(conversation.greeting.get().getGreeting(), StringStartsWith.startsWith(CzechGreeting.GREETING));
+ }
+
+ public static class ProviderInject2 {
+ @Inject
+ Provider<Greeting2> greeting;
+ }
+
+ public static class ProviderContext2 {
+ @Context
+ Provider<Greeting2> greeting;
+ }
+
+ public static class ProviderInject {
+ @Inject
+ Provider<Greeting> greeting;
+ }
+
+ public static class ProviderContext {
+ @Context
+ Provider<Greeting> greeting;
+ }
+
+ @Vetoed
+ static class SupplierGreeting implements Supplier<Greeting2> {
+
+ private final String greetingType;
+
+ /**
+ * Default constructor.
+ */
+ public SupplierGreeting() {
+ this(CzechGreeting.GREETING);
+ }
+
+ /**
+ * Supplier's constructor.
+ *
+ * @param greetingType greetingType in a specific language.
+ */
+ public SupplierGreeting(String greetingType) {
+ this.greetingType = greetingType;
+ }
+
+ @Override
+ public Greeting2 get() {
+ if (CzechGreeting.GREETING.equals(greetingType)) {
+ return new CzechGreeting2();
+ } else {
+ return new EnglishGreeting2();
+ }
+ }
+ }
+
+ @Vetoed
+ static class EnglishGreeting2 extends EnglishGreeting implements Greeting2 {
+ }
+
+ @Vetoed
+ static class CzechGreeting2 extends CzechGreeting implements Greeting2 {
+ }
+
+ @Vetoed
+ static class EnglishGreeting implements Greeting, Printable {
+
+ static final String GREETING = "Hello";
+
+ @Override
+ public String getGreeting() {
+ return GREETING + "#" + Thread.currentThread().getName();
+ }
+
+ @Override
+ public void print() {
+ System.out.println(GREETING);
+ }
+
+ @Override
+ public String toString() {
+ return "EnglishGreeting";
+ }
+ }
+
+ @Vetoed
+ static class CzechGreeting implements Greeting, Printable {
+
+ static final String GREETING = "Ahoj";
+
+ @Override
+ public String getGreeting() {
+ return GREETING + "#" + Thread.currentThread().getName();
+ }
+
+ @Override
+ public void print() {
+ System.out.println(GREETING);
+ }
+
+ @Override
+ public String toString() {
+ return "CzechGreeting";
+ }
+ }
+
+ @FunctionalInterface
+ interface Greeting2 {
+ String getGreeting();
+ }
+
+ @FunctionalInterface
+ interface Greeting {
+ String getGreeting();
+ }
+
+ @FunctionalInterface
+ public interface Printable {
+ void print();
+ }
+
+ private static class ProviderInjectionTestExtension implements Extension {
+ void registerBindings(@Observes BeforeBeanDiscovery beforeBeanDiscovery, BeanManager beanManager) {
+ AbstractBinder testBinder = new AbstractBinder() {
+ @Override
+ protected void configure() {
+ bind(CzechGreeting.class).to(Greeting.class);
+ bindAsContract(ProviderInject.class);
+ bindAsContract(ProviderContext.class);
+
+ bindFactory(SupplierGreeting.class).to(Greeting2.class);
+ bindAsContract(ProviderInject2.class);
+ bindAsContract(ProviderContext2.class);
+ }
+ };
+
+ beanManager.getExtension(BinderRegisterExtension.class).register(beforeBeanDiscovery, testBinder.getBindings());
+ }
+ }
+}
diff --git a/incubator/cdi-inject-weld/src/test/java/org/glassfish/jersey/inject/weld/internal/managed/SupplierClassBindingTest.java b/incubator/cdi-inject-weld/src/test/java/org/glassfish/jersey/inject/weld/internal/managed/SupplierClassBindingTest.java
new file mode 100644
index 0000000..bf10029
--- /dev/null
+++ b/incubator/cdi-inject-weld/src/test/java/org/glassfish/jersey/inject/weld/internal/managed/SupplierClassBindingTest.java
@@ -0,0 +1,312 @@
+/*
+ * Copyright (c) 2021 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.inject.weld.internal.managed;
+
+import java.util.function.Supplier;
+
+import javax.enterprise.event.Observes;
+import javax.enterprise.inject.Vetoed;
+import javax.enterprise.inject.se.SeContainerInitializer;
+import javax.enterprise.inject.spi.BeanManager;
+import javax.enterprise.inject.spi.BeforeBeanDiscovery;
+import javax.enterprise.inject.spi.Extension;
+import javax.inject.Inject;
+import javax.inject.Singleton;
+
+import org.glassfish.jersey.internal.inject.AbstractBinder;
+
+import org.hamcrest.core.StringStartsWith;
+import org.junit.BeforeClass;
+import org.junit.Test;
+import static org.junit.Assert.assertNotSame;
+import static org.junit.Assert.assertSame;
+import static org.junit.Assert.assertThat;
+
+/**
+ * Tests that {@link Supplier} can be registered as a class-factory.
+ */
+@Vetoed
+public class SupplierClassBindingTest extends TestParent {
+
+ public static final String GREET = "Hi";
+
+ @BeforeClass
+ public static void setup() {
+ SeContainerInitializer containerInitializer = SeContainerInitializer.newInstance();
+ containerInitializer.addExtensions(new SupplierClassBindingTestExtension());
+ container = containerInitializer.initialize();
+ }
+
+ @Test
+ public void testMessages() {
+// BindingTestHelper.bind(injectionManager, binder -> {
+// binder.bindFactory(SupplierGreeting.class).to(Greeting.class);
+// binder.bindAsContract(Conversation.class);
+// });
+
+ Conversation conversation = injectionManager.getInstance(Conversation.class);
+ assertThat(conversation.greeting.getGreeting(), StringStartsWith.startsWith(GREET));
+ }
+
+ @Test
+ public void testSupplierPerLookupInstancePerLookup() {
+// BindingTestHelper.bind(injectionManager, binder -> {
+// binder.bindFactory(SupplierGreeting.class).to(Greeting.class);
+// binder.bindAsContract(Conversation.class);
+// });
+
+ Conversation conversation1 = injectionManager.getInstance(Conversation.class);
+ Greeting greeting1 = conversation1.greeting;
+ Conversation conversation2 = injectionManager.getInstance(Conversation.class);
+ Greeting greeting2 = conversation2.greeting;
+ Conversation conversation3 = injectionManager.getInstance(Conversation.class);
+ Greeting greeting3 = conversation3.greeting;
+
+ assertNotSame(greeting1, greeting2);
+ assertNotSame(greeting2, greeting3);
+
+ Supplier<Greeting> supplier1 = injectionManager.getInstance(Conversation.class).greetingSupplier;
+ Supplier<Greeting> supplier2 = injectionManager.getInstance(Conversation.class).greetingSupplier;
+ Supplier<Greeting> supplier3 = injectionManager.getInstance(Conversation.class).greetingSupplier;
+
+ assertNotSame(supplier1, supplier2);
+ assertNotSame(supplier2, supplier3);
+ }
+
+ @Test
+ public void testSupplierSingletonInstancePerLookup() {
+// BindingTestHelper.bind(injectionManager, binder -> {
+// binder.bindFactory(SupplierSingletonInstancePerLookup.class, Singleton.class)
+// .to(GreetingSupplierSingletonInstancePerLookup.class);
+// binder.bindAsContract(ConversationSupplierSingletonInstancePerLookup.class);
+// });
+
+ GreetingSupplierSingletonInstancePerLookup greeting1 = injectionManager
+ .getInstance(ConversationSupplierSingletonInstancePerLookup.class).greeting;
+ GreetingSupplierSingletonInstancePerLookup greeting2 = injectionManager
+ .getInstance(ConversationSupplierSingletonInstancePerLookup.class).greeting;
+ GreetingSupplierSingletonInstancePerLookup greeting3 = injectionManager
+ .getInstance(ConversationSupplierSingletonInstancePerLookup.class).greeting;
+
+ assertNotSame(greeting1, greeting2);
+ assertNotSame(greeting2, greeting3);
+
+ Supplier<GreetingSupplierSingletonInstancePerLookup> supplier1 = injectionManager
+ .getInstance(ConversationSupplierSingletonInstancePerLookup.class).greetingSupplier;
+ Supplier<GreetingSupplierSingletonInstancePerLookup> supplier2 = injectionManager
+ .getInstance(ConversationSupplierSingletonInstancePerLookup.class).greetingSupplier;
+ Supplier<GreetingSupplierSingletonInstancePerLookup> supplier3 = injectionManager
+ .getInstance(ConversationSupplierSingletonInstancePerLookup.class).greetingSupplier;
+
+ assertSame(supplier1, supplier2);
+ assertSame(supplier2, supplier3);
+ }
+
+ @Test
+ public void testSupplierPerLookupInstanceSingleton() {
+// BindingTestHelper.bind(injectionManager, binder -> {
+// binder.bindFactory(SupplierPerLookupInstanceSingleton.class)
+// .to(GreetingSupplierPerLookupInstanceSingleton.class).in(Singleton.class);
+// binder.bindAsContract(ConversationSupplierPerLookupInstanceSingleton.class);
+// });
+
+ GreetingSupplierPerLookupInstanceSingleton greeting1 = injectionManager
+ .getInstance(ConversationSupplierPerLookupInstanceSingleton.class).greeting;
+ GreetingSupplierPerLookupInstanceSingleton greeting2 = injectionManager
+ .getInstance(ConversationSupplierPerLookupInstanceSingleton.class).greeting;
+ GreetingSupplierPerLookupInstanceSingleton greeting3 = injectionManager
+ .getInstance(ConversationSupplierPerLookupInstanceSingleton.class).greeting;
+
+ assertSame(greeting1, greeting2);
+ assertSame(greeting2, greeting3);
+
+ Supplier<GreetingSupplierPerLookupInstanceSingleton> supplier1 = injectionManager
+ .getInstance(ConversationSupplierPerLookupInstanceSingleton.class).greetingSupplier;
+ Supplier<GreetingSupplierPerLookupInstanceSingleton> supplier2 = injectionManager
+ .getInstance(ConversationSupplierPerLookupInstanceSingleton.class).greetingSupplier;
+ Supplier<GreetingSupplierPerLookupInstanceSingleton> supplier3 = injectionManager
+ .getInstance(ConversationSupplierPerLookupInstanceSingleton.class).greetingSupplier;
+
+ assertNotSame(supplier1, supplier2);
+ assertNotSame(supplier2, supplier3);
+ }
+
+ @Test
+ public void testSupplierSingletonInstanceSingleton() {
+// BindingTestHelper.bind(injectionManager, binder -> {
+// binder.bindFactory(SupplierSingletonInstanceSingleton.class, Singleton.class)
+// .to(GreetingSupplierSingletonInstanceSingleton.class).in(Singleton.class);
+// binder.bindAsContract(ConversationSupplierSingletonInstanceSingleton.class);
+// });
+
+ GreetingSupplierSingletonInstanceSingleton greeting1 = injectionManager
+ .getInstance(ConversationSupplierSingletonInstanceSingleton.class).greeting;
+ GreetingSupplierSingletonInstanceSingleton greeting2 = injectionManager
+ .getInstance(ConversationSupplierSingletonInstanceSingleton.class).greeting;
+ GreetingSupplierSingletonInstanceSingleton greeting3 = injectionManager
+ .getInstance(ConversationSupplierSingletonInstanceSingleton.class).greeting;
+
+ assertSame(greeting1, greeting2);
+ assertSame(greeting2, greeting3);
+
+ Supplier<GreetingSupplierSingletonInstanceSingleton> supplier1 = injectionManager
+ .getInstance(ConversationSupplierSingletonInstanceSingleton.class).greetingSupplier;
+ Supplier<GreetingSupplierSingletonInstanceSingleton> supplier2 = injectionManager
+ .getInstance(ConversationSupplierSingletonInstanceSingleton.class).greetingSupplier;
+ Supplier<GreetingSupplierSingletonInstanceSingleton> supplier3 = injectionManager
+ .getInstance(ConversationSupplierSingletonInstanceSingleton.class).greetingSupplier;
+
+ assertSame(supplier1, supplier2);
+ assertSame(supplier2, supplier3);
+ }
+
+ @Vetoed
+ static class SupplierSingletonInstanceSingleton implements Supplier<GreetingSupplierSingletonInstanceSingleton> {
+ @Override
+ public GreetingSupplierSingletonInstanceSingleton get() {
+ return new GreetingSupplierSingletonInstanceSingleton() {
+ @Override
+ public String getGreeting() {
+ return GREET;
+ }
+ };
+ }
+ }
+
+ @Vetoed
+ static class ConversationSupplierSingletonInstanceSingleton {
+ @Inject
+ GreetingSupplierSingletonInstanceSingleton greeting;
+
+ @Inject
+ Supplier<GreetingSupplierSingletonInstanceSingleton> greetingSupplier;
+ }
+
+ @FunctionalInterface
+ static interface GreetingSupplierSingletonInstanceSingleton {
+ String getGreeting();
+ }
+
+ // ---
+
+ @Vetoed
+ static class SupplierPerLookupInstanceSingleton implements Supplier<GreetingSupplierPerLookupInstanceSingleton> {
+ @Override
+ public GreetingSupplierPerLookupInstanceSingleton get() {
+ return () -> GREET;
+ }
+ }
+
+ @Vetoed
+ static class ConversationSupplierPerLookupInstanceSingleton {
+ @Inject
+ GreetingSupplierPerLookupInstanceSingleton greeting;
+
+ @Inject
+ Supplier<GreetingSupplierPerLookupInstanceSingleton> greetingSupplier;
+ }
+
+ @FunctionalInterface
+ static interface GreetingSupplierPerLookupInstanceSingleton {
+ String getGreeting();
+ }
+
+ // ---
+
+ @Vetoed
+ static class SupplierSingletonInstancePerLookup implements Supplier<GreetingSupplierSingletonInstancePerLookup> {
+ @Override
+ public GreetingSupplierSingletonInstancePerLookup get() {
+ return new GreetingSupplierSingletonInstancePerLookup() { // Using Lambda will provide singletons
+ @Override
+ public String getGreeting() {
+ return GREET;
+ }
+ };
+ }
+ }
+
+ @Vetoed
+ static class ConversationSupplierSingletonInstancePerLookup {
+ @Inject
+ GreetingSupplierSingletonInstancePerLookup greeting;
+
+ @Inject
+ Supplier<GreetingSupplierSingletonInstancePerLookup> greetingSupplier;
+ }
+
+ @FunctionalInterface
+ static interface GreetingSupplierSingletonInstancePerLookup {
+ String getGreeting();
+ }
+
+ // ---
+
+ @Vetoed
+ static class SupplierGreeting implements Supplier<Greeting> {
+ @Override
+ public Greeting get() {
+ return new Greeting() { // Using Lambda will provide singletons
+ @Override
+ public String getGreeting() {
+ return GREET;
+ }
+ };
+ }
+ }
+
+ @Vetoed
+ static class Conversation {
+ @Inject
+ Greeting greeting;
+
+ @Inject
+ Supplier<Greeting> greetingSupplier;
+ }
+
+ @FunctionalInterface
+ static interface Greeting {
+ String getGreeting();
+ }
+
+ private static class SupplierClassBindingTestExtension implements Extension {
+ void registerBindings(@Observes BeforeBeanDiscovery beforeBeanDiscovery, BeanManager beanManager) {
+ AbstractBinder testBinder = new AbstractBinder() {
+ @Override
+ protected void configure() {
+ bindFactory(SupplierGreeting.class).to(Greeting.class);
+ bindAsContract(Conversation.class);
+
+ bindFactory(SupplierSingletonInstancePerLookup.class, Singleton.class)
+ .to(GreetingSupplierSingletonInstancePerLookup.class);
+ bindAsContract(ConversationSupplierSingletonInstancePerLookup.class);
+
+ bindFactory(SupplierPerLookupInstanceSingleton.class)
+ .to(GreetingSupplierPerLookupInstanceSingleton.class).in(Singleton.class);
+ bindAsContract(ConversationSupplierPerLookupInstanceSingleton.class);
+
+ bindFactory(SupplierSingletonInstanceSingleton.class, Singleton.class)
+ .to(GreetingSupplierSingletonInstanceSingleton.class).in(Singleton.class);
+ bindAsContract(ConversationSupplierSingletonInstanceSingleton.class);
+ }
+ };
+
+ beanManager.getExtension(BinderRegisterExtension.class).register(beforeBeanDiscovery, testBinder.getBindings());
+ }
+ }
+
+}
diff --git a/incubator/cdi-inject-weld/src/test/java/org/glassfish/jersey/inject/weld/internal/managed/SupplierContractsTest.java b/incubator/cdi-inject-weld/src/test/java/org/glassfish/jersey/inject/weld/internal/managed/SupplierContractsTest.java
new file mode 100644
index 0000000..8f576e1
--- /dev/null
+++ b/incubator/cdi-inject-weld/src/test/java/org/glassfish/jersey/inject/weld/internal/managed/SupplierContractsTest.java
@@ -0,0 +1,322 @@
+/*
+ * Copyright (c) 2021 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.inject.weld.internal.managed;
+
+import javax.enterprise.event.Observes;
+import javax.enterprise.inject.Vetoed;
+import javax.enterprise.inject.se.SeContainer;
+import javax.enterprise.inject.se.SeContainerInitializer;
+import javax.enterprise.inject.spi.BeanManager;
+import javax.enterprise.inject.spi.BeforeBeanDiscovery;
+import javax.enterprise.inject.spi.Extension;
+import javax.inject.Singleton;
+
+import org.glassfish.jersey.internal.inject.AbstractBinder;
+import org.glassfish.jersey.internal.inject.InjectionManager;
+
+import org.glassfish.jersey.internal.inject.Injections;
+import org.jboss.weld.exceptions.DeploymentException;
+import org.junit.After;
+import org.junit.Test;
+
+import java.util.function.Consumer;
+
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNotSame;
+import static org.junit.Assert.assertSame;
+
+/**
+ * Tests that {@link java.util.function.Supplier} can contain multiple contracts.
+ *
+ * @author Petr Bouda
+ */
+@Vetoed
+public class SupplierContractsTest {
+
+ protected static SeContainer container;
+ protected InjectionManager injectionManager;
+
+ public void setup(Consumer<AbstractBinder> binding) {
+ Extension extension = new Extension() {
+ void registerBindings(@Observes BeforeBeanDiscovery beforeBeanDiscovery, BeanManager beanManager) {
+ AbstractBinder testBinder = new AbstractBinder() {
+ @Override
+ protected void configure() {
+ binding.accept(this);
+ }
+ };
+ beanManager.getExtension(BinderRegisterExtension.class).register(beforeBeanDiscovery, testBinder.getBindings());
+ }
+ };
+
+ SeContainerInitializer containerInitializer = SeContainerInitializer.newInstance();
+ containerInitializer.addExtensions(extension);
+ container = containerInitializer.initialize();
+ injectionManager = Injections.createInjectionManager();
+ }
+
+ @After
+ public void tearDown() throws Exception {
+ if (container != null && container.isRunning()) {
+ container.close();
+ }
+ }
+
+ @Test
+ public void testClassFactoryInstanceInterface() {
+// setup(new SupplierContractsTestExtension() {
+// @Override
+// void bind(AbstractBinder binder) {
+// binder.bindFactory(SupplierGreeting.class).to(Greeting.class);
+// binder.bindAsContract(Conversation.class);
+// }
+// });
+
+ setup((binder) -> {
+ binder.bindFactory(SupplierGreeting.class).to(Greeting.class);
+ binder.bindAsContract(Conversation.class);
+ });
+
+ Conversation conversation = injectionManager.getInstance(Conversation.class);
+ assertNotNull(conversation.greeting);
+ assertNotNull(conversation.greetingSupplier.get());
+ }
+
+ @Test
+ public void testClassFactoryInstanceImplementation() {
+// BindingTestHelper.bind(injectionManager, binder -> {
+// binder.bindFactory(SupplierGreeting.class).to(CzechGreeting.class);
+// binder.bindAsContract(CzechConversation.class);
+// });
+ setup((binder) -> {
+ binder.bindFactory(SupplierGreeting.class).to(CzechGreeting.class);
+ binder.bindAsContract(CzechConversation.class);
+ });
+
+ CzechConversation conversation = injectionManager.getInstance(CzechConversation.class);
+ assertNotNull(conversation.greeting);
+ assertNotNull(conversation.greetingSupplier.get());
+ }
+
+ @Test
+ public void testInstanceFactoryInstanceInterface() {
+ setup((binder) -> {
+ binder.bindFactory(new SupplierGreeting()).to(Greeting.class);
+ binder.bindAsContract(Conversation.class);
+ });
+
+ BindingTestHelper.bind(injectionManager, binder -> {
+ binder.bindFactory(new SupplierGreeting()).to(Greeting.class);
+// binder.bindAsContract(Conversation.class);
+ });
+
+ Conversation conversation = injectionManager.getInstance(Conversation.class);
+ assertNotNull(conversation.greeting);
+ assertNotNull(conversation.greetingSupplier.get());
+ }
+
+ @Test
+ public void testInstanceFactoryInstanceImplementation() {
+ setup((binder) -> {
+ binder.bindFactory(new SupplierGreeting()).to(CzechGreeting.class);
+ binder.bindAsContract(CzechConversation.class);
+ });
+
+ BindingTestHelper.bind(injectionManager, binder -> {
+ binder.bindFactory(new SupplierGreeting()).to(CzechGreeting.class);
+// binder.bindAsContract(CzechConversation.class);
+ });
+
+ CzechConversation conversation = injectionManager.getInstance(CzechConversation.class);
+ assertNotNull(conversation.greeting);
+ assertNotNull(conversation.greetingSupplier.get());
+ }
+
+ @Test
+ public void testClassFactoryMultipleContracts() {
+// BindingTestHelper.bind(injectionManager, binder -> {
+// binder.bindFactory(SupplierGreeting.class)
+// .to(Greeting.class)
+// .to(Printable.class);
+// binder.bindAsContract(PrintableConversation.class);
+// });
+
+ setup((binder) -> {
+ binder.bindFactory(SupplierGreeting.class).to(Greeting.class).to(Printable.class);
+ binder.bindAsContract(PrintableConversation.class);
+ });
+
+ PrintableConversation conversation = injectionManager.getInstance(PrintableConversation.class);
+ assertNotNull(conversation.greeting);
+ assertNotNull(conversation.printable);
+ assertNotNull(conversation.greetingSupplier);
+ assertNotNull(conversation.printableSupplier);
+
+ assertNotSame(conversation.greeting, conversation.printable);
+ assertNotSame(conversation.greetingSupplier, conversation.printableSupplier);
+ }
+
+ @Test
+ public void testClassFactorySingletonMultipleContracts() {
+// BindingTestHelper.bind(injectionManager, binder -> {
+// binder.bindFactory(SupplierGreeting.class, Singleton.class)
+// .to(Greeting.class)
+// .to(Printable.class);
+// binder.bindAsContract(PrintableConversation.class);
+// });
+
+ setup((binder) -> {
+ binder.bindFactory(SupplierGreeting.class, Singleton.class).to(Greeting.class).to(Printable.class);
+ binder.bindAsContract(PrintableConversation.class);
+ });
+
+ PrintableConversation conversation = injectionManager.getInstance(PrintableConversation.class);
+ assertNotNull(conversation.greeting);
+ assertNotNull(conversation.printable);
+ assertNotNull(conversation.greetingSupplier);
+ assertNotNull(conversation.printableSupplier);
+
+ assertNotSame(conversation.greeting, conversation.printable);
+ assertSame(conversation.greetingSupplier, conversation.printableSupplier);
+ }
+
+ @Test
+ public void testClassFactoryMultipleContractsSingleton() {
+// BindingTestHelper.bind(injectionManager, binder -> {
+// binder.bindFactory(SupplierGreeting.class)
+// .to(Greeting.class)
+// .to(Printable.class)
+// .in(Singleton.class);
+// binder.bindAsContract(PrintableConversation.class);
+// });
+
+ setup((binder) -> {
+ binder.bindFactory(SupplierGreeting.class).to(Greeting.class).to(Printable.class).in(Singleton.class);
+ binder.bindAsContract(PrintableConversation.class);
+ });
+
+ PrintableConversation conversation = injectionManager.getInstance(PrintableConversation.class);
+ assertNotNull(conversation.greeting);
+ assertNotNull(conversation.printable);
+ assertNotNull(conversation.greetingSupplier);
+ assertNotNull(conversation.printableSupplier);
+
+ assertSame(conversation.greeting, conversation.printable);
+ assertNotSame(conversation.greetingSupplier, conversation.printableSupplier);
+ }
+
+ @Test
+ public void testInstanceFactoryMultipleContracts() {
+// BindingTestHelper.bind(injectionManager, binder -> {
+// binder.bindFactory(new SupplierGreeting())
+// .to(Greeting.class)
+// .to(Printable.class);
+// binder.bindAsContract(PrintableConversation.class);
+// });
+
+ setup((binder) -> {
+ binder.bindFactory(new SupplierGreeting()).to(Greeting.class).to(Printable.class);
+ binder.bindAsContract(PrintableConversation.class);
+ });
+
+ BindingTestHelper.bind(injectionManager, binder -> {
+ binder.bindFactory(new SupplierGreeting())
+ .to(Greeting.class)
+ .to(Printable.class);
+// binder.bindAsContract(PrintableConversation.class);
+ });
+
+ PrintableConversation conversation = injectionManager.getInstance(PrintableConversation.class);
+ assertNotNull(conversation.greeting);
+ assertNotNull(conversation.printable);
+ assertNotNull(conversation.greetingSupplier);
+ assertNotNull(conversation.printableSupplier);
+
+ assertNotSame(conversation.greeting, conversation.printable);
+ assertSame(conversation.greetingSupplier, conversation.printableSupplier);
+ }
+
+ @Test
+ public void testInstanceFactoryMultipleContractsSingleton() {
+ setup((binder) -> {
+ binder.bindFactory(new SupplierGreeting()).to(Greeting.class).to(Printable.class).in(Singleton.class);
+ binder.bindAsContract(PrintableConversation.class);
+ });
+
+ BindingTestHelper.bind(injectionManager, binder -> {
+ binder.bindFactory(new SupplierGreeting())
+ .to(Greeting.class)
+ .to(Printable.class)
+ .in(Singleton.class);
+// binder.bindAsContract(PrintableConversation.class);
+ });
+
+ PrintableConversation conversation = injectionManager.getInstance(PrintableConversation.class);
+ assertNotNull(conversation.greeting);
+ assertNotNull(conversation.printable);
+ assertNotNull(conversation.greetingSupplier);
+ assertNotNull(conversation.printableSupplier);
+
+ assertSame(conversation.greeting, conversation.printable);
+ assertSame(conversation.greetingSupplier, conversation.printableSupplier);
+ }
+
+ @Test(expected = DeploymentException.class)
+ public void testClassFactoryFailedWrongImplementation() {
+// BindingTestHelper.bind(injectionManager, binder -> {
+// binder.bindFactory(SupplierGreeting.class).to(EnglishGreeting.class);
+// binder.bindAsContract(Conversation.class);
+// });
+
+ setup((binder) -> {
+ binder.bindFactory(SupplierGreeting.class).to(EnglishGreeting.class);
+ binder.bindAsContract(Conversation.class);
+ });
+
+ injectionManager.getInstance(Conversation.class);
+ }
+
+ @Test(expected = DeploymentException.class)
+ public void testInstanceFactoryFailsWrongImplementation() {
+ setup((binder) -> {
+ binder.bindFactory(new SupplierGreeting()).to(EnglishGreeting.class);
+ binder.bindAsContract(Conversation.class);
+ });
+
+ BindingTestHelper.bind(injectionManager, binder -> {
+ binder.bindFactory(new SupplierGreeting()).to(EnglishGreeting.class);
+// binder.bindAsContract(Conversation.class);
+ });
+
+ injectionManager.getInstance(Conversation.class);
+ }
+
+ @Test(expected = DeploymentException.class)
+ public void testFailsImplementationButInterfaceExpected() {
+ setup((binder) -> {
+ binder.bindFactory(new SupplierGreeting()).to(CzechGreeting.class);
+ binder.bindAsContract(Conversation.class);
+ });
+
+ BindingTestHelper.bind(injectionManager, binder -> {
+ binder.bindFactory(new SupplierGreeting()).to(CzechGreeting.class);
+// binder.bindAsContract(Conversation.class);
+ });
+
+ injectionManager.getInstance(Conversation.class);
+ }
+}
diff --git a/incubator/cdi-inject-weld/src/test/java/org/glassfish/jersey/inject/weld/internal/managed/SupplierGreeting.java b/incubator/cdi-inject-weld/src/test/java/org/glassfish/jersey/inject/weld/internal/managed/SupplierGreeting.java
new file mode 100644
index 0000000..2f97170
--- /dev/null
+++ b/incubator/cdi-inject-weld/src/test/java/org/glassfish/jersey/inject/weld/internal/managed/SupplierGreeting.java
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 2021 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.inject.weld.internal.managed;
+
+import java.util.function.Supplier;
+
+import javax.enterprise.inject.Vetoed;
+
+/**
+ * @author Petr Bouda
+ */
+@Vetoed
+public class SupplierGreeting implements Supplier<Greeting> {
+
+ private final String greetingType;
+
+ /**
+ * Default constructor.
+ */
+ public SupplierGreeting() {
+ this(CzechGreeting.GREETING);
+ }
+
+ /**
+ * Supplier's constructor.
+ *
+ * @param greetingType greetingType in a specific language.
+ */
+ public SupplierGreeting(String greetingType) {
+ this.greetingType = greetingType;
+ }
+
+ @Override
+ public Greeting get() {
+ if (CzechGreeting.GREETING.equals(greetingType)) {
+ return new CzechGreeting();
+ } else {
+ return new EnglishGreeting();
+ }
+ }
+}
diff --git a/incubator/cdi-inject-weld/src/test/java/org/glassfish/jersey/inject/weld/internal/managed/SupplierInstanceBindingTest.java b/incubator/cdi-inject-weld/src/test/java/org/glassfish/jersey/inject/weld/internal/managed/SupplierInstanceBindingTest.java
new file mode 100644
index 0000000..eb90843
--- /dev/null
+++ b/incubator/cdi-inject-weld/src/test/java/org/glassfish/jersey/inject/weld/internal/managed/SupplierInstanceBindingTest.java
@@ -0,0 +1,239 @@
+/*
+ * Copyright (c) 2021 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.inject.weld.internal.managed;
+
+import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.function.Supplier;
+
+import javax.enterprise.event.Observes;
+import javax.enterprise.inject.se.SeContainerInitializer;
+import javax.enterprise.inject.spi.BeanManager;
+import javax.enterprise.inject.spi.BeforeBeanDiscovery;
+import javax.enterprise.inject.spi.Extension;
+import javax.enterprise.inject.Vetoed;
+import javax.inject.Inject;
+import javax.ws.rs.core.GenericType;
+
+import org.glassfish.jersey.internal.inject.AbstractBinder;
+
+import org.hamcrest.core.StringStartsWith;
+import org.junit.Before;
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotSame;
+import static org.junit.Assert.assertSame;
+import static org.junit.Assert.assertThat;
+
+/**
+ * Tests that {@link Supplier} can be registered as a instance-factory.
+ *
+ * @author Petr Bouda
+ */
+@Vetoed
+public class SupplierInstanceBindingTest extends TestParent {
+
+ private static long supplierHit = 2;
+ private static AtomicBoolean runOnlyOnceGuard = new AtomicBoolean(false);
+
+ @BeforeClass
+ public static void setup() {
+ SeContainerInitializer containerInitializer = SeContainerInitializer.newInstance();
+ containerInitializer.addExtensions(new SupplierInstanceBindingTestExtension());
+ container = containerInitializer.initialize();
+ }
+
+ @Before
+ public void initBinding() {
+ if (!runOnlyOnceGuard.getAndSet(true)) {
+ MyVetoedLongSupplier supplier = new MyVetoedLongSupplier();
+ supplier.get();
+ supplier.get();
+
+ BindingTestHelper.bind(injectionManager, binder ->
+ binder.bindFactory(supplier).to(Long.class));
+
+ BindingTestHelper.bind(injectionManager, binder -> {
+ binder.bindFactory(new SupplierGreeting()).to(Greeting.class);
+ });
+ }
+ }
+
+ @Test
+ public void testInstanceFactorySupplierOnly() {
+// MyVetoedLongSupplier supplier = new MyVetoedLongSupplier();
+// supplier.get();
+// supplier.get();
+//
+// BindingTestHelper.bind(injectionManager, binder ->
+// binder.bindFactory(supplier).to(Long.class));
+
+ Supplier<Long> instance = injectionManager.getInstance(new GenericType<Supplier<Long>>() {
+ }.getType());
+ assertEquals((Long) (supplierHit++ + 1), instance.get());
+ assertEquals((Long) (supplierHit++ + 1), instance.get());
+ }
+
+ @Test
+ public void testInstanceFactoryValuesOnly() {
+// MyVetoedLongSupplier supplier = new MyVetoedLongSupplier();
+// supplier.get();
+// supplier.get();
+//
+// BindingTestHelper.bind(injectionManager, binder ->
+// binder.bindFactory(supplier).to(Long.class));
+
+ Long instance3 = injectionManager.getInstance(Long.class);
+ Long instance4 = injectionManager.getInstance(Long.class);
+
+ assertEquals((Long) (supplierHit++ + 1), instance3);
+ assertEquals((Long) (supplierHit++ + 1), instance4);
+ }
+
+ @Test
+ public void testMessages() {
+// BindingTestHelper.bind(injectionManager, binder -> {
+// binder.bindFactory(new SupplierGreeting()).to(Greeting.class);
+// binder.bindAsContract(Conversation.class);
+// });
+
+ Conversation conversation = injectionManager.getInstance(Conversation.class);
+ assertThat(conversation.greeting.getGreeting(), StringStartsWith.startsWith(CzechGreeting.GREETING));
+ }
+
+ @Test
+ public void testSupplierSingletonInstancePerLookup() {
+// BindingTestHelper.bind(injectionManager, binder -> {
+// binder.bindFactory(new SupplierGreeting()).to(Greeting.class);
+// binder.bindAsContract(Conversation.class);
+// });
+
+ Greeting greeting1 = injectionManager.getInstance(Conversation.class).greeting;
+ Greeting greeting2 = injectionManager.getInstance(Conversation.class).greeting;
+ Greeting greeting3 = injectionManager.getInstance(Conversation.class).greeting;
+
+ assertNotSame(greeting1, greeting2);
+ assertNotSame(greeting2, greeting3);
+
+ Supplier<Greeting> supplier1 = injectionManager.getInstance(Conversation.class).greetingSupplier;
+ Supplier<Greeting> supplier2 = injectionManager.getInstance(Conversation.class).greetingSupplier;
+ Supplier<Greeting> supplier3 = injectionManager.getInstance(Conversation.class).greetingSupplier;
+
+ assertSame(supplier1, supplier2);
+ assertSame(supplier2, supplier3);
+ }
+
+ @Vetoed
+ static class Conversation {
+ @Inject
+ Greeting greeting;
+
+ @Inject
+ Supplier<Greeting> greetingSupplier;
+ }
+
+ @Vetoed
+ static class SupplierGreeting implements Supplier<Greeting> {
+
+ private final String greetingType;
+
+ /**
+ * Default constructor.
+ */
+ public SupplierGreeting() {
+ this(CzechGreeting.GREETING);
+ }
+
+ /**
+ * Supplier's constructor.
+ *
+ * @param greetingType greetingType in a specific language.
+ */
+ public SupplierGreeting(String greetingType) {
+ this.greetingType = greetingType;
+ }
+
+ @Override
+ public Greeting get() {
+ if (CzechGreeting.GREETING.equals(greetingType)) {
+ return new CzechGreeting();
+ } else {
+ return new EnglishGreeting();
+ }
+ }
+ }
+
+ static class EnglishGreeting implements Greeting {
+
+ static final String GREETING = "Hello";
+
+ @Override
+ public String getGreeting() {
+ return GREETING + "#" + Thread.currentThread().getName();
+ }
+
+ @Override
+ public String toString() {
+ return "EnglishGreeting";
+ }
+ }
+
+ static class CzechGreeting implements Greeting {
+
+ static final String GREETING = "Ahoj";
+
+ @Override
+ public String getGreeting() {
+ return GREETING + "#" + Thread.currentThread().getName();
+ }
+
+ @Override
+ public String toString() {
+ return "CzechGreeting";
+ }
+ }
+
+ @FunctionalInterface
+ static interface Greeting {
+ /**
+ * Returns greeting in a specific language.
+ *
+ * @return type of the greeting.
+ */
+ String getGreeting();
+ }
+
+ private static class SupplierInstanceBindingTestExtension implements Extension {
+ void registerBindings(@Observes BeforeBeanDiscovery beforeBeanDiscovery, BeanManager beanManager) {
+ AbstractBinder testBinder = new AbstractBinder() {
+ @Override
+ protected void configure() {
+ MyVetoedLongSupplier supplier = new MyVetoedLongSupplier();
+ supplier.get();
+ supplier.get();
+ bindFactory(supplier).to(Long.class);
+
+ bindFactory(new SupplierGreeting()).to(Greeting.class);
+ bindAsContract(Conversation.class);
+ }
+ };
+
+ beanManager.getExtension(BinderRegisterExtension.class).register(beforeBeanDiscovery, testBinder.getBindings());
+ }
+ }
+}
diff --git a/incubator/cdi-inject-weld/src/test/java/org/glassfish/jersey/inject/weld/internal/managed/TestParent.java b/incubator/cdi-inject-weld/src/test/java/org/glassfish/jersey/inject/weld/internal/managed/TestParent.java
new file mode 100644
index 0000000..0938dd2
--- /dev/null
+++ b/incubator/cdi-inject-weld/src/test/java/org/glassfish/jersey/inject/weld/internal/managed/TestParent.java
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2021 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.inject.weld.internal.managed;
+
+import javax.enterprise.inject.se.SeContainer;
+import javax.enterprise.inject.se.SeContainerInitializer;
+import org.glassfish.jersey.internal.inject.InjectionManager;
+import org.glassfish.jersey.internal.inject.Injections;
+import org.junit.AfterClass;
+import org.junit.Before;
+import org.junit.BeforeClass;
+
+public class TestParent {
+ protected static SeContainer container;
+ protected InjectionManager injectionManager;
+
+
+ @BeforeClass
+ public static void setup() {
+ SeContainerInitializer containerInitializer = SeContainerInitializer.newInstance();
+ container = containerInitializer.initialize();
+ }
+
+ @Before
+ public void init() {
+ injectionManager = Injections.createInjectionManager();
+ }
+
+ @AfterClass
+ public static void tearDown() throws Exception {
+ container.close();
+ }
+
+}
diff --git a/incubator/cdi-inject-weld/src/test/java/org/glassfish/jersey/inject/weld/internal/managed/TestPreinitialization.java b/incubator/cdi-inject-weld/src/test/java/org/glassfish/jersey/inject/weld/internal/managed/TestPreinitialization.java
new file mode 100644
index 0000000..a9096b0
--- /dev/null
+++ b/incubator/cdi-inject-weld/src/test/java/org/glassfish/jersey/inject/weld/internal/managed/TestPreinitialization.java
@@ -0,0 +1,116 @@
+/*
+ * Copyright (c) 2021 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.inject.weld.internal.managed;
+
+import javax.enterprise.context.Dependent;
+import javax.inject.Singleton;
+import javax.ws.rs.RuntimeType;
+
+import org.glassfish.jersey.inject.weld.spi.BootstrapPreinitialization;
+import org.glassfish.jersey.internal.inject.AbstractBinder;
+import org.glassfish.jersey.internal.inject.PerThread;
+import org.glassfish.jersey.process.internal.RequestScoped;
+
+public class TestPreinitialization implements BootstrapPreinitialization {
+ @Override
+ public void register(RuntimeType runtimeType, AbstractBinder binder) {
+ if (RuntimeType.CLIENT == runtimeType) {
+ //ClientInstanceInjectionTest
+ {
+ binder.bindFactory(ClientInstanceInjectionTest.InjectableClientServerSupplierClient.class)
+ .to(ClientInstanceInjectionTest.InjectableClientServer.class);
+ }
+ return;
+ }
+
+ // Disposable supplier test
+ {
+ binder.bindFactory(DisposableSupplierTest.DisposableSupplierImpl.class, Singleton.class)
+ .to(DisposableSupplierTest.StringForSupplierSingletonClass.class);
+ binder.bindFactory(DisposableSupplierTest.DisposableSupplierImpl.class)
+ .to(DisposableSupplierTest.StringForSupplierClass.class);
+ binder.bindFactory(new DisposableSupplierTest.DisposableSupplierImpl())
+ .to(DisposableSupplierTest.StringForSupplierInstance.class);
+ binder.bindFactory(SupplierGreeting.class)
+ .to(DisposableSupplierTest.GreetingsClass.class);
+ binder.bindFactory(new SupplierGreeting())
+ .to(DisposableSupplierTest.GreetingsInstance.class);
+
+ binder.bindFactory(DisposableSupplierTest.ProxiableDisposableSingletonSupplierImpl.class, Singleton.class)
+ .to(DisposableSupplierTest.ProxiableHolderSingletonClass.class)
+ .in(RequestScoped.class);
+ binder.bindFactory(DisposableSupplierTest.ProxiableDisposableSupplierImpl.class)
+ .to(DisposableSupplierTest.ProxiableHolderClass.class)
+ .in(RequestScoped.class);
+
+ binder.bindFactory(DisposableSupplierTest.DisposableSupplierForComposedImpl.class, Singleton.class)
+ .to(DisposableSupplierTest.StringForComposed.class);
+ binder.bindAsContract(DisposableSupplierTest.ComposedObject.class)
+ .in(RequestScoped.class);
+ }
+
+ // ThreadScopeTest
+ {
+ //testThreadScopedInDifferentThread
+ binder.bindAsContract(ThreadScopeTest.SingletonObject.class)
+ .in(Singleton.class);
+ binder.bindFactory(new ThreadScopeTest.SupplierGreeting())
+ .to(ThreadScopeTest.Greeting.class)
+ .in(PerThread.class);
+
+ //testThreadScopedInRequestScope
+ binder.bindAsContract(ThreadScopeTest.RequestScopedInterface.class)
+ .in(javax.enterprise.context.RequestScoped.class);
+// bindFactory(new SupplierGreeting())
+// .to(Greeting.class)
+// .in(PerThread.class);
+
+ //testThreadScopedInRequestScopeImplementation
+ binder.bindAsContract(ThreadScopeTest.RequestScopedCzech.class)
+ .in(javax.enterprise.context.RequestScoped.class);
+ binder.bindFactory(new ThreadScopeTest.SupplierGreeting())
+ .to(ThreadScopeTest.CzechGreeting.class)
+ .in(PerThread.class);
+
+ //testThreadScopedInRequestTwoTypes
+ binder.bindAsContract(ThreadScopeTest.RequestScopedCzech2.class)
+ .in(javax.enterprise.context.RequestScoped.class);
+ binder.bindAsContract(ThreadScopeTest.RequestScopedEnglish2.class)
+ .in(javax.enterprise.context.RequestScoped.class);
+ binder.bindFactory(new ThreadScopeTest.SupplierGreeting2(ThreadScopeTest.CzechGreeting2.GREETING))
+ .to(ThreadScopeTest.CzechGreeting2.class)
+ .in(PerThread.class);
+ binder.bindFactory(new ThreadScopeTest.SupplierGreeting2(ThreadScopeTest.EnglishGreeting2.GREETING))
+ .to(ThreadScopeTest.EnglishGreeting2.class)
+ .in(PerThread.class);
+ }
+
+ //ClientInstanceInjectionTest
+ {
+ binder.bind(new ClientInstanceInjectionTest.StringInjectable(0))
+ .to(ClientInstanceInjectionTest.Injectable.class).in(Dependent.class);
+ binder.bindAsContract(ClientInstanceInjectionTest.InjectedBean.class);
+
+ binder.bindFactory(new ClientInstanceInjectionTest.StringInjectableSupplier2(0))
+ .to(ClientInstanceInjectionTest.Injectable2.class).in(Dependent.class);
+ //bindAsContract(ClientInstanceInjectionTest.InjectedSupplierBean.class);
+
+ binder.bindFactory(ClientInstanceInjectionTest.InjectableClientServerSupplierServer.class)
+ .to(ClientInstanceInjectionTest.InjectableClientServer.class);
+ }
+ }
+}
diff --git a/incubator/cdi-inject-weld/src/test/java/org/glassfish/jersey/inject/weld/internal/managed/ThreadScopeTest.java b/incubator/cdi-inject-weld/src/test/java/org/glassfish/jersey/inject/weld/internal/managed/ThreadScopeTest.java
new file mode 100644
index 0000000..e3fc4d2
--- /dev/null
+++ b/incubator/cdi-inject-weld/src/test/java/org/glassfish/jersey/inject/weld/internal/managed/ThreadScopeTest.java
@@ -0,0 +1,397 @@
+/*
+ * Copyright (c) 2021 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.inject.weld.internal.managed;
+
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.function.Supplier;
+
+import javax.enterprise.context.RequestScoped;
+import javax.enterprise.inject.Vetoed;
+import javax.inject.Inject;
+import javax.inject.Singleton;
+
+import org.glassfish.jersey.internal.inject.PerThread;
+import org.glassfish.jersey.process.internal.RequestScope;
+
+import org.hamcrest.core.StringStartsWith;
+import org.junit.Before;
+import org.junit.Test;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNotSame;
+import static org.junit.Assert.assertThat;
+
+/**
+ * Testing thread scope integration.
+ *
+ * @author Petr Bouda
+ */
+public class ThreadScopeTest extends TestParent {
+
+ private static AtomicBoolean runOnlyOnceGuard = new AtomicBoolean(false);
+
+ @Before
+ public void initOnce() {
+ if (!runOnlyOnceGuard.getAndSet(true)) {
+ BindingTestHelper.bind(injectionManager, binder -> {
+ binder.bindFactory(new SupplierGreeting())
+ .to(Greeting.class)
+ .in(PerThread.class);
+ });
+ }
+ }
+
+ @Test
+ public void testThreadScopedInDifferentThread() throws InterruptedException {
+// InjectionManager injectionManager = BindingTestHelper.createInjectionManager();
+// BindingTestHelper.bind(injectionManager, binder -> {
+// binder.bindAsContract(SingletonObject.class)
+// .in(Singleton.class);
+//
+// binder.bindFactory(new SupplierGreeting())
+// .to(Greeting.class)
+// .in(PerThread.class);
+// });
+
+ SingletonObject instance1 = injectionManager.getInstance(SingletonObject.class);
+ Greeting greeting1 = instance1.getGreeting();
+ String greetingString1 = greeting1.getGreeting();
+ assertThat(greetingString1, StringStartsWith.startsWith(CzechGreeting.GREETING));
+
+ CountDownLatch latch = new CountDownLatch(1);
+ new Thread(() -> {
+ // Precisely the same object
+ SingletonObject instance2 = injectionManager.getInstance(SingletonObject.class);
+ Greeting greeting2 = instance2.getGreeting();
+ String greetingString2 = greeting2.getGreeting();
+ assertThat(greetingString2, StringStartsWith.startsWith(CzechGreeting.GREETING));
+
+ assertNotEquals(greetingString1, greetingString2);
+ latch.countDown();
+ }).start();
+
+ latch.await();
+
+ SingletonObject instance3 = injectionManager.getInstance(SingletonObject.class);
+ assertEquals(instance3.getGreeting().getGreeting(), greetingString1);
+ }
+
+ @Test
+ public void testThreadScopedInRequestScope() {
+// InjectionManager injectionManager = BindingTestHelper.createInjectionManager();
+// BindingTestHelper.bind(injectionManager, binder -> {
+// binder.bindAsContract(RequestScopedInterface.class)
+// .in(RequestScoped.class);
+//
+// binder.bindFactory(new SupplierGreeting())
+// .to(Greeting.class)
+// .in(PerThread.class);
+// });
+
+ RequestScope request = injectionManager.getInstance(RequestScope.class);
+ request.runInScope(() -> {
+ RequestScopedInterface instance1 = injectionManager.getInstance(RequestScopedInterface.class);
+ Greeting greeting1 = instance1.getGreeting();
+ assertNotNull(greeting1);
+
+ // Precisely the same object
+ RequestScopedInterface instance2 = injectionManager.getInstance(RequestScopedInterface.class);
+ Greeting greeting2 = instance2.getGreeting();
+ assertNotNull(greeting2);
+
+ assertEquals(greeting1, greeting2);
+ });
+ }
+
+ @Test
+ public void testThreadScopedInRequestScopeImplementation() {
+// InjectionManager injectionManager = BindingTestHelper.createInjectionManager();
+// BindingTestHelper.bind(injectionManager, binder -> {
+// binder.bindAsContract(RequestScopedCzech.class)
+// .in(RequestScoped.class);
+//
+// binder.bindFactory(new SupplierGreeting())
+// .to(CzechGreeting.class)
+// .in(PerThread.class);
+// });
+
+ RequestScope request = injectionManager.getInstance(RequestScope.class);
+ request.runInScope(() -> {
+ RequestScopedCzech instance1 = injectionManager.getInstance(RequestScopedCzech.class);
+ CzechGreeting greeting1 = instance1.getGreeting();
+ assertNotNull(greeting1);
+
+ // Precisely the same object
+ RequestScopedCzech instance2 = injectionManager.getInstance(RequestScopedCzech.class);
+ CzechGreeting greeting2 = instance2.getGreeting();
+ assertNotNull(greeting2);
+
+ assertEquals(greeting1, greeting2);
+ });
+ }
+
+ @Test
+ public void testThreadScopedInRequestTwoTypes() {
+// InjectionManager injectionManager = BindingTestHelper.createInjectionManager();
+// BindingTestHelper.bind(injectionManager, binder -> {
+// binder.bindAsContract(RequestScopedCzech.class)
+// .in(RequestScoped.class);
+//
+// binder.bindAsContract(RequestScopedEnglish.class)
+// .in(RequestScoped.class);
+//
+// binder.bindFactory(new SupplierGreeting(CzechGreeting.GREETING))
+// .to(CzechGreeting.class)
+// .in(PerThread.class);
+//
+// binder.bindFactory(new SupplierGreeting(EnglishGreeting.GREETING))
+// .to(EnglishGreeting.class)
+// .in(PerThread.class);
+// });
+
+ RequestScope request = injectionManager.getInstance(RequestScope.class);
+ request.runInScope(() -> {
+ RequestScopedCzech2 instance1 = injectionManager.getInstance(RequestScopedCzech2.class);
+ CzechGreeting2 greeting1 = instance1.getGreeting();
+ assertNotNull(greeting1);
+
+ // Precisely the same object
+ RequestScopedEnglish2 instance2 = injectionManager.getInstance(RequestScopedEnglish2.class);
+ EnglishGreeting2 greeting2 = instance2.getGreeting();
+ assertNotNull(greeting2);
+
+ assertNotSame(greeting1, greeting2);
+ });
+ }
+
+ @Test
+ public void testThreadScopedInSingletonScope() {
+// InjectionManager injectionManager = BindingTestHelper.createInjectionManager();
+// BindingTestHelper.bind(injectionManager, binder -> {
+// binder.bindAsContract(SingletonObject.class)
+// .in(Singleton.class);
+//
+// binder.bindFactory(new SupplierGreeting())
+// .to(Greeting.class)
+// .in(PerThread.class);
+// });
+
+ SingletonObject instance1 = injectionManager.getInstance(SingletonObject.class);
+ Greeting greeting1 = instance1.getGreeting();
+ assertNotNull(greeting1);
+
+ // Precisely the same object
+ SingletonObject instance2 = injectionManager.getInstance(SingletonObject.class);
+ Greeting greeting2 = instance2.getGreeting();
+ assertNotNull(greeting2);
+
+ assertEquals(greeting1, greeting2);
+ }
+
+ @RequestScoped
+ public static class RequestScopedInterface {
+
+ @Inject
+ Greeting greeting;
+
+ public Greeting getGreeting() {
+ return greeting;
+ }
+ }
+
+ @RequestScoped
+ public static class RequestScopedCzech {
+
+ @Inject
+ CzechGreeting greeting;
+
+ public CzechGreeting getGreeting() {
+ return greeting;
+ }
+ }
+
+ @Singleton
+ public static class SingletonObject {
+
+ @Inject
+ Greeting greeting;
+
+ public Greeting getGreeting() {
+ return greeting;
+ }
+ }
+
+ @RequestScoped
+ public static class RequestScopedCzech2 {
+
+ @Inject
+ CzechGreeting2 greeting;
+
+ public CzechGreeting2 getGreeting() {
+ return greeting;
+ }
+ }
+
+ @RequestScoped
+ public static class RequestScopedEnglish2 {
+
+ @Inject
+ EnglishGreeting2 greeting;
+
+ public EnglishGreeting2 getGreeting() {
+ return greeting;
+ }
+ }
+
+ @Vetoed
+ static class SupplierGreeting2 implements Supplier<Greeting2> {
+
+ private final String greetingType;
+
+ /**
+ * Default constructor.
+ */
+ public SupplierGreeting2() {
+ this(CzechGreeting.GREETING);
+ }
+
+ /**
+ * Supplier's constructor.
+ *
+ * @param greetingType greetingType in a specific language.
+ */
+ public SupplierGreeting2(String greetingType) {
+ this.greetingType = greetingType;
+ }
+
+ @Override
+ public Greeting2 get() {
+ if (CzechGreeting2.GREETING.equals(greetingType)) {
+ return new CzechGreeting2();
+ } else {
+ return new EnglishGreeting2();
+ }
+ }
+ }
+
+ @Vetoed
+ static class CzechGreeting2 implements Greeting2 {
+
+ static final String GREETING = "Ahoj";
+
+ @Override
+ public String getGreeting() {
+ return GREETING + "#" + Thread.currentThread().getName();
+ }
+
+ @Override
+ public String toString() {
+ return "CzechGreeting";
+ }
+ }
+
+ @Vetoed
+ static class EnglishGreeting2 implements Greeting2 {
+
+ static final String GREETING = "Hello";
+
+ @Override
+ public String getGreeting() {
+ return GREETING + "#" + Thread.currentThread().getName();
+ }
+
+ @Override
+ public String toString() {
+ return "EnglishGreeting";
+ }
+ }
+
+ @Vetoed
+ static class SupplierGreeting implements Supplier<Greeting> {
+
+ private final String greetingType;
+
+ /**
+ * Default constructor.
+ */
+ public SupplierGreeting() {
+ this(CzechGreeting.GREETING);
+ }
+
+ /**
+ * Supplier's constructor.
+ *
+ * @param greetingType greetingType in a specific language.
+ */
+ public SupplierGreeting(String greetingType) {
+ this.greetingType = greetingType;
+ }
+
+ @Override
+ public Greeting get() {
+ if (CzechGreeting.GREETING.equals(greetingType)) {
+ return new CzechGreeting();
+ } else {
+ return new EnglishGreeting();
+ }
+ }
+ }
+
+ @Vetoed
+ static class EnglishGreeting implements Greeting {
+
+ static final String GREETING = "Hello";
+
+ @Override
+ public String getGreeting() {
+ return GREETING + "#" + Thread.currentThread().getName();
+ }
+
+ @Override
+ public String toString() {
+ return "EnglishGreeting";
+ }
+ }
+
+ @Vetoed
+ static class CzechGreeting implements Greeting {
+
+ static final String GREETING = "Ahoj";
+
+ @Override
+ public String getGreeting() {
+ return GREETING + "#" + Thread.currentThread().getName();
+ }
+
+ @Override
+ public String toString() {
+ return "CzechGreeting";
+ }
+ }
+
+ @FunctionalInterface
+ static interface Greeting2 {
+ String getGreeting();
+ }
+
+ @FunctionalInterface
+ static interface Greeting {
+ String getGreeting();
+ }
+}
diff --git a/incubator/cdi-inject-weld/src/test/resources/META-INF/beans.xml b/incubator/cdi-inject-weld/src/test/resources/META-INF/beans.xml
new file mode 100644
index 0000000..678e3dc
--- /dev/null
+++ b/incubator/cdi-inject-weld/src/test/resources/META-INF/beans.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ Copyright (c) 2021 Oracle and/or its affiliates. All rights reserved.
+
+ This program and the accompanying materials are made available under the
+ terms of the Eclipse Public License v. 2.0, which is available at
+ http://www.eclipse.org/legal/epl-2.0.
+
+ This Source Code may also be made available under the following Secondary
+ Licenses when the conditions for such availability set forth in the
+ Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ version 2 with the GNU Classpath Exception, which is available at
+ https://www.gnu.org/software/classpath/license.html.
+
+ SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+
+-->
+
+<beans bean-discovery-mode="annotated" />
diff --git a/incubator/cdi-inject-weld/src/test/resources/META-INF/services/org.glassfish.jersey.inject.weld.spi.BootstrapPreinitialization b/incubator/cdi-inject-weld/src/test/resources/META-INF/services/org.glassfish.jersey.inject.weld.spi.BootstrapPreinitialization
new file mode 100644
index 0000000..7909bcf
--- /dev/null
+++ b/incubator/cdi-inject-weld/src/test/resources/META-INF/services/org.glassfish.jersey.inject.weld.spi.BootstrapPreinitialization
@@ -0,0 +1,17 @@
+
+# Copyright (c) 2021 Oracle and/or its affiliates. All rights reserved.
+#
+# This program and the accompanying materials are made available under the
+# terms of the Eclipse Public License v. 2.0, which is available at
+# http://www.eclipse.org/legal/epl-2.0.
+#
+# This Source Code may also be made available under the following Secondary
+# Licenses when the conditions for such availability set forth in the
+# Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+# version 2 with the GNU Classpath Exception, which is available at
+# https://www.gnu.org/software/classpath/license.html.
+#
+# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+#
+
+org.glassfish.jersey.inject.weld.internal.managed.TestPreinitialization
\ No newline at end of file
diff --git a/incubator/pom.xml b/incubator/pom.xml
index fd6b57b..930f5f8 100644
--- a/incubator/pom.xml
+++ b/incubator/pom.xml
@@ -36,6 +36,7 @@
</description>
<modules>
+ <module>cdi-inject-weld</module>
<module>declarative-linking</module>
<module>gae-integration</module>
<module>html-json</module>
diff --git a/tests/e2e-inject/cdi-inject-weld/pom.xml b/tests/e2e-inject/cdi-inject-weld/pom.xml
new file mode 100644
index 0000000..60690bf
--- /dev/null
+++ b/tests/e2e-inject/cdi-inject-weld/pom.xml
@@ -0,0 +1,87 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ Copyright (c) 2021 Oracle and/or its affiliates. All rights reserved.
+
+ This program and the accompanying materials are made available under the
+ terms of the Eclipse Public License v. 2.0, which is available at
+ http://www.eclipse.org/legal/epl-2.0.
+
+ This Source Code may also be made available under the following Secondary
+ Licenses when the conditions for such availability set forth in the
+ Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ version 2 with the GNU Classpath Exception, which is available at
+ https://www.gnu.org/software/classpath/license.html.
+
+ SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+
+-->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>org.glassfish.jersey.tests</groupId>
+ <artifactId>e2e-inject</artifactId>
+ <version>2.35-SNAPSHOT</version>
+ </parent>
+
+ <artifactId>e2e-inject-cdi-inject-weld</artifactId>
+ <packaging>jar</packaging>
+ <name>jersey-tests-e2e-inject-cdi-inject-weld</name>
+
+ <description>Jersey E2E Inject CDI SE tests</description>
+
+ <dependencies>
+ <dependency>
+ <groupId>jakarta.enterprise</groupId>
+ <artifactId>jakarta.enterprise.cdi-api</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.jboss.weld.se</groupId>
+ <artifactId>weld-se-core</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.glassfish.jersey.incubator</groupId>
+ <artifactId>jersey-cdi-inject-weld</artifactId>
+ <version>${project.version}</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.glassfish.jersey.core</groupId>
+ <artifactId>jersey-server</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.glassfish.jersey.test-framework.providers</groupId>
+ <artifactId>jersey-test-framework-provider-bundle</artifactId>
+ <type>pom</type>
+ <scope>test</scope>
+ <exclusions>
+ <exclusion>
+ <groupId>org.glassfish.jersey.media</groupId>
+ <artifactId>jersey-media-jaxb</artifactId>
+ </exclusion>
+ <exclusion>
+ <groupId>jakarta.xml.bind</groupId>
+ <artifactId>jakarta.xml.bind-api</artifactId>
+ </exclusion>
+ </exclusions>
+ </dependency>
+ <dependency>
+ <groupId>org.glassfish.jersey.test-framework</groupId>
+ <artifactId>jersey-test-framework-util</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.hamcrest</groupId>
+ <artifactId>hamcrest-library</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>junit</groupId>
+ <artifactId>junit</artifactId>
+ <scope>test</scope>
+ </dependency>
+ </dependencies>
+</project>
diff --git a/tests/e2e-inject/cdi-inject-weld/src/main/java/org/glassfish/jersey/tests/e2e/inject/cdi/weld/Account.java b/tests/e2e-inject/cdi-inject-weld/src/main/java/org/glassfish/jersey/tests/e2e/inject/cdi/weld/Account.java
new file mode 100644
index 0000000..c09845a
--- /dev/null
+++ b/tests/e2e-inject/cdi-inject-weld/src/main/java/org/glassfish/jersey/tests/e2e/inject/cdi/weld/Account.java
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2021 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.inject.cdi.weld;
+
+import javax.enterprise.context.ApplicationScoped;
+import javax.enterprise.event.Observes;
+
+/**
+ * Keeps current state of money.
+ *
+ * @author Petr Bouda
+ */
+@ApplicationScoped
+public class Account {
+
+ private long current = 0;
+
+ public void observeCredit(@Observes @Credit Long amount) {
+ current += amount;
+ }
+
+ public void observeDebit(@Observes @Debit Long amount) {
+ current -= amount;
+ }
+
+ public long getCurrent() {
+ return current;
+ }
+}
diff --git a/tests/e2e-inject/cdi-inject-weld/src/main/java/org/glassfish/jersey/tests/e2e/inject/cdi/weld/AccountResource.java b/tests/e2e-inject/cdi-inject-weld/src/main/java/org/glassfish/jersey/tests/e2e/inject/cdi/weld/AccountResource.java
new file mode 100644
index 0000000..49ef2a9
--- /dev/null
+++ b/tests/e2e-inject/cdi-inject-weld/src/main/java/org/glassfish/jersey/tests/e2e/inject/cdi/weld/AccountResource.java
@@ -0,0 +1,61 @@
+/*
+ * Copyright (c) 2021 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.inject.cdi.weld;
+
+import javax.ws.rs.DELETE;
+import javax.ws.rs.GET;
+import javax.ws.rs.POST;
+import javax.ws.rs.Path;
+import javax.ws.rs.QueryParam;
+
+import javax.enterprise.event.Event;
+import javax.inject.Inject;
+
+/**
+ * Testing resource for CDI events.
+ *
+ * @author Petr Bouda
+ */
+@Path("account")
+public class AccountResource {
+
+ @Inject
+ @Credit
+ private Event<Long> creditEvent;
+
+ @Inject
+ @Debit
+ private Event<Long> debitEvent;
+
+ @Inject
+ private Account account;
+
+ @POST
+ public void credit(@QueryParam("amount") long amount) {
+ creditEvent.fire(amount);
+ }
+
+ @DELETE
+ public void debit(@QueryParam("amount") long amount) {
+ debitEvent.fire(amount);
+ }
+
+ @GET
+ public long current() {
+ return account.getCurrent();
+ }
+}
diff --git a/tests/e2e-inject/cdi-inject-weld/src/main/java/org/glassfish/jersey/tests/e2e/inject/cdi/weld/Credit.java b/tests/e2e-inject/cdi-inject-weld/src/main/java/org/glassfish/jersey/tests/e2e/inject/cdi/weld/Credit.java
new file mode 100644
index 0000000..14ed675
--- /dev/null
+++ b/tests/e2e-inject/cdi-inject-weld/src/main/java/org/glassfish/jersey/tests/e2e/inject/cdi/weld/Credit.java
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2021 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.inject.cdi.weld;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.Target;
+
+import javax.inject.Qualifier;
+
+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;
+
+/**
+ * Event qualifier.
+ *
+ * @author Petr Bouda
+ */
+@Qualifier
+@Target({METHOD, FIELD, PARAMETER, TYPE})
+@Retention(RUNTIME)
+public @interface Credit {
+}
diff --git a/tests/e2e-inject/cdi-inject-weld/src/main/java/org/glassfish/jersey/tests/e2e/inject/cdi/weld/Debit.java b/tests/e2e-inject/cdi-inject-weld/src/main/java/org/glassfish/jersey/tests/e2e/inject/cdi/weld/Debit.java
new file mode 100644
index 0000000..56d60d9
--- /dev/null
+++ b/tests/e2e-inject/cdi-inject-weld/src/main/java/org/glassfish/jersey/tests/e2e/inject/cdi/weld/Debit.java
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2021 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.inject.cdi.weld;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.Target;
+
+import javax.inject.Qualifier;
+
+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;
+
+/**
+ * Event qualifier.
+ *
+ * @author Petr Bouda
+ */
+@Qualifier
+@Target({METHOD, FIELD, PARAMETER, TYPE})
+@Retention(RUNTIME)
+public @interface Debit {
+}
diff --git a/tests/e2e-inject/cdi-inject-weld/src/main/java/org/glassfish/jersey/tests/e2e/inject/cdi/weld/Hello.java b/tests/e2e-inject/cdi-inject-weld/src/main/java/org/glassfish/jersey/tests/e2e/inject/cdi/weld/Hello.java
new file mode 100644
index 0000000..8d9fc45
--- /dev/null
+++ b/tests/e2e-inject/cdi-inject-weld/src/main/java/org/glassfish/jersey/tests/e2e/inject/cdi/weld/Hello.java
@@ -0,0 +1,28 @@
+/*
+ * Copyright (c) 2021 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.inject.cdi.weld;
+
+/**
+ * Interface used to activate decorator.
+ *
+ * @author Petr Bouda
+ */
+public interface Hello {
+
+ String hello();
+
+}
diff --git a/tests/e2e-inject/cdi-inject-weld/src/main/java/org/glassfish/jersey/tests/e2e/inject/cdi/weld/HelloResource.java b/tests/e2e-inject/cdi-inject-weld/src/main/java/org/glassfish/jersey/tests/e2e/inject/cdi/weld/HelloResource.java
new file mode 100644
index 0000000..512506f
--- /dev/null
+++ b/tests/e2e-inject/cdi-inject-weld/src/main/java/org/glassfish/jersey/tests/e2e/inject/cdi/weld/HelloResource.java
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2021 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.inject.cdi.weld;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+
+import javax.inject.Inject;
+import org.glassfish.jersey.tests.e2e.inject.cdi.weld.subresources.MyBean;
+
+/**
+ * Intercepted and decorated resource.
+ *
+ * @author Petr Bouda
+ */
+@Secured
+@Path("intercepted")
+public class HelloResource implements Hello {
+
+ @Inject
+ private NameService service;
+
+ @Inject
+ MyBean mybean;
+
+ @GET
+ @Override
+ public String hello() {
+ System.out.println(mybean.hello());
+ return "Hello " + service.getName();
+ }
+}
diff --git a/tests/e2e-inject/cdi-inject-weld/src/main/java/org/glassfish/jersey/tests/e2e/inject/cdi/weld/HelloStarDecorator.java b/tests/e2e-inject/cdi-inject-weld/src/main/java/org/glassfish/jersey/tests/e2e/inject/cdi/weld/HelloStarDecorator.java
new file mode 100644
index 0000000..cbd3ad7
--- /dev/null
+++ b/tests/e2e-inject/cdi-inject-weld/src/main/java/org/glassfish/jersey/tests/e2e/inject/cdi/weld/HelloStarDecorator.java
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2021 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.inject.cdi.weld;
+
+import javax.decorator.Decorator;
+import javax.decorator.Delegate;
+import javax.enterprise.inject.Any;
+import javax.inject.Inject;
+
+/**
+ * Decorator wraps the hello resource by stars.
+ *
+ * @author Petr Bouda
+ */
+@Decorator
+public class HelloStarDecorator implements Hello {
+
+ @Inject
+ @Delegate
+ @Any
+ Hello account;
+
+ @Override
+ public String hello() {
+ return "***" + account.hello() + "***";
+ }
+}
diff --git a/tests/e2e-inject/cdi-inject-weld/src/main/java/org/glassfish/jersey/tests/e2e/inject/cdi/weld/JaxrsService.java b/tests/e2e-inject/cdi-inject-weld/src/main/java/org/glassfish/jersey/tests/e2e/inject/cdi/weld/JaxrsService.java
new file mode 100644
index 0000000..2847170
--- /dev/null
+++ b/tests/e2e-inject/cdi-inject-weld/src/main/java/org/glassfish/jersey/tests/e2e/inject/cdi/weld/JaxrsService.java
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2021 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.inject.cdi.weld;
+
+import javax.ws.rs.core.Context;
+import javax.ws.rs.core.UriInfo;
+
+import javax.enterprise.context.ApplicationScoped;
+
+/**
+ * Holder for JAX-RS information to inject them into interceptor. JAX-RS does not work in interceptor.
+ *
+ * @author Petr Bouda
+ */
+@ApplicationScoped
+public class JaxrsService {
+
+ @Context
+ private UriInfo uriInfo;
+
+ public UriInfo getUriInfo() {
+ return uriInfo;
+ }
+}
diff --git a/tests/e2e-inject/cdi-inject-weld/src/main/java/org/glassfish/jersey/tests/e2e/inject/cdi/weld/NameService.java b/tests/e2e-inject/cdi-inject-weld/src/main/java/org/glassfish/jersey/tests/e2e/inject/cdi/weld/NameService.java
new file mode 100644
index 0000000..5205ffb
--- /dev/null
+++ b/tests/e2e-inject/cdi-inject-weld/src/main/java/org/glassfish/jersey/tests/e2e/inject/cdi/weld/NameService.java
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2021 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.inject.cdi.weld;
+
+import javax.enterprise.context.ApplicationScoped;
+
+/**
+ * Service returning the name.
+ *
+ * @author Petr Bouda
+ */
+@ApplicationScoped
+public class NameService {
+
+ public static final String NAME = "James";
+
+ public String getName() {
+ return NAME;
+ }
+}
diff --git a/tests/e2e-inject/cdi-inject-weld/src/main/java/org/glassfish/jersey/tests/e2e/inject/cdi/weld/Secured.java b/tests/e2e-inject/cdi-inject-weld/src/main/java/org/glassfish/jersey/tests/e2e/inject/cdi/weld/Secured.java
new file mode 100644
index 0000000..f3971ea
--- /dev/null
+++ b/tests/e2e-inject/cdi-inject-weld/src/main/java/org/glassfish/jersey/tests/e2e/inject/cdi/weld/Secured.java
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2021 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.inject.cdi.weld;
+
+import java.lang.annotation.Inherited;
+import java.lang.annotation.Retention;
+import java.lang.annotation.Target;
+
+import javax.interceptor.InterceptorBinding;
+
+import static java.lang.annotation.ElementType.METHOD;
+import static java.lang.annotation.ElementType.TYPE;
+import static java.lang.annotation.RetentionPolicy.RUNTIME;
+
+/**
+ * Security annotation bound to {@link SecurityInterceptor}.
+ *
+ * @author Petr Bouda
+ */
+@Inherited
+@InterceptorBinding
+@Retention(RUNTIME)
+@Target({ METHOD, TYPE })
+public @interface Secured {
+}
diff --git a/tests/e2e-inject/cdi-inject-weld/src/main/java/org/glassfish/jersey/tests/e2e/inject/cdi/weld/SecurityInterceptor.java b/tests/e2e-inject/cdi-inject-weld/src/main/java/org/glassfish/jersey/tests/e2e/inject/cdi/weld/SecurityInterceptor.java
new file mode 100644
index 0000000..a2e3966
--- /dev/null
+++ b/tests/e2e-inject/cdi-inject-weld/src/main/java/org/glassfish/jersey/tests/e2e/inject/cdi/weld/SecurityInterceptor.java
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 2021 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.inject.cdi.weld;
+
+import javax.ws.rs.ForbiddenException;
+import javax.ws.rs.core.MultivaluedMap;
+
+import javax.inject.Inject;
+import javax.interceptor.AroundInvoke;
+import javax.interceptor.Interceptor;
+import javax.interceptor.InvocationContext;
+
+/**
+ * Interceptor checking James as a user in query params.
+ *
+ * @author Petr Bouda
+ */
+@Secured
+@Interceptor
+public class SecurityInterceptor {
+
+ @Inject
+ NameService nameService;
+
+ @Inject
+ JaxrsService jaxrsService;
+
+ @AroundInvoke
+ public Object logMethodEntry(InvocationContext ctx) throws Exception {
+ MultivaluedMap<String, String> params = jaxrsService.getUriInfo().getQueryParameters();
+ String user = params.getFirst("user");
+
+ if (nameService.getName().equals(user)) {
+ return ctx.proceed();
+ } else {
+ throw new ForbiddenException("Forbidden resource for the user: " + user);
+ }
+ }
+}
diff --git a/tests/e2e-inject/cdi-inject-weld/src/main/java/org/glassfish/jersey/tests/e2e/inject/cdi/weld/scopes/ApplicationCounterBean.java b/tests/e2e-inject/cdi-inject-weld/src/main/java/org/glassfish/jersey/tests/e2e/inject/cdi/weld/scopes/ApplicationCounterBean.java
new file mode 100644
index 0000000..9835419
--- /dev/null
+++ b/tests/e2e-inject/cdi-inject-weld/src/main/java/org/glassfish/jersey/tests/e2e/inject/cdi/weld/scopes/ApplicationCounterBean.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2021 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.inject.cdi.weld.scopes;
+
+import java.util.concurrent.atomic.AtomicInteger;
+
+import javax.enterprise.context.ApplicationScoped;
+
+/**
+ * Request counter.
+ *
+ * @author Petr Bouda
+ */
+@ApplicationScoped
+public class ApplicationCounterBean {
+
+ private AtomicInteger counter = new AtomicInteger();
+
+ public int getNumber() {
+ return counter.incrementAndGet();
+ }
+}
diff --git a/tests/e2e-inject/cdi-inject-weld/src/main/java/org/glassfish/jersey/tests/e2e/inject/cdi/weld/scopes/RequestScopedResource.java b/tests/e2e-inject/cdi-inject-weld/src/main/java/org/glassfish/jersey/tests/e2e/inject/cdi/weld/scopes/RequestScopedResource.java
new file mode 100644
index 0000000..1e24e8d
--- /dev/null
+++ b/tests/e2e-inject/cdi-inject-weld/src/main/java/org/glassfish/jersey/tests/e2e/inject/cdi/weld/scopes/RequestScopedResource.java
@@ -0,0 +1,57 @@
+/*
+ * Copyright (c) 2021 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.inject.cdi.weld.scopes;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.PathParam;
+import javax.ws.rs.Produces;
+import javax.ws.rs.core.Context;
+import javax.ws.rs.core.UriInfo;
+
+import javax.inject.Inject;
+
+import org.glassfish.jersey.process.internal.RequestScoped;
+
+/**
+ * Request scoped resource.
+ *
+ * @author Petr Bouda
+ */
+@RequestScoped
+@Path("request")
+public class RequestScopedResource {
+
+ @Inject
+ private ApplicationCounterBean application;
+
+ @PathParam("name")
+ private String name;
+
+ private UriInfo uriInfo;
+
+ public RequestScopedResource(@Context UriInfo uriInfo) {
+ this.uriInfo = uriInfo;
+ }
+
+ @GET
+ @Path("{name}")
+ @Produces("text/plain")
+ public String getHello() {
+ return "Hello_" + name + " [" + application.getNumber() + "] " + "[" + uriInfo.getPath() + "] " + this;
+ }
+}
diff --git a/tests/e2e-inject/cdi-inject-weld/src/main/java/org/glassfish/jersey/tests/e2e/inject/cdi/weld/scopes/SingletonScopedResource.java b/tests/e2e-inject/cdi-inject-weld/src/main/java/org/glassfish/jersey/tests/e2e/inject/cdi/weld/scopes/SingletonScopedResource.java
new file mode 100644
index 0000000..ed32ad1
--- /dev/null
+++ b/tests/e2e-inject/cdi-inject-weld/src/main/java/org/glassfish/jersey/tests/e2e/inject/cdi/weld/scopes/SingletonScopedResource.java
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 2021 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.inject.cdi.weld.scopes;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.PathParam;
+import javax.ws.rs.Produces;
+import javax.ws.rs.core.Context;
+import javax.ws.rs.core.UriInfo;
+
+import javax.inject.Inject;
+import javax.inject.Singleton;
+
+/**
+ * Singleton Resource.
+ *
+ * @author Petr Bouda
+ */
+@Singleton
+@Path("singleton")
+public class SingletonScopedResource {
+
+ @Inject
+ private ApplicationCounterBean application;
+
+ @Context
+ private UriInfo uriInfo;
+
+ @GET
+ @Path("{name}")
+ @Produces("text/plain")
+ public String getHello(@PathParam("name") String name) {
+ return "Hello_" + name + " [" + application.getNumber() + "] " + "[" + uriInfo.getPath() + "] " + this;
+ }
+}
diff --git a/tests/e2e-inject/cdi-inject-weld/src/main/java/org/glassfish/jersey/tests/e2e/inject/cdi/weld/subresources/ModelProcessorFeature.java b/tests/e2e-inject/cdi-inject-weld/src/main/java/org/glassfish/jersey/tests/e2e/inject/cdi/weld/subresources/ModelProcessorFeature.java
new file mode 100644
index 0000000..7eb9357
--- /dev/null
+++ b/tests/e2e-inject/cdi-inject-weld/src/main/java/org/glassfish/jersey/tests/e2e/inject/cdi/weld/subresources/ModelProcessorFeature.java
@@ -0,0 +1,130 @@
+/*
+ * Copyright (c) 2021 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.inject.cdi.weld.subresources;
+
+import javax.enterprise.context.ApplicationScoped;
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.container.ContainerRequestContext;
+import javax.ws.rs.core.Configuration;
+import javax.ws.rs.core.Feature;
+import javax.ws.rs.core.FeatureContext;
+
+import javax.annotation.Priority;
+import javax.inject.Singleton;
+
+import org.glassfish.jersey.process.Inflector;
+import org.glassfish.jersey.process.internal.RequestScoped;
+import org.glassfish.jersey.server.model.ModelProcessor;
+import org.glassfish.jersey.server.model.Resource;
+import org.glassfish.jersey.server.model.ResourceModel;
+
+@ApplicationScoped
+public class ModelProcessorFeature implements Feature {
+
+ @Override
+ public boolean configure(FeatureContext context) {
+ context.register(SimpleModelProcessor.class);
+ return true;
+ }
+
+ @Priority(5000)
+ public static class SimpleModelProcessor implements ModelProcessor {
+
+ @Override
+ public ResourceModel processResourceModel(ResourceModel resourceModel, Configuration configuration) {
+ ResourceModel.Builder builder = new ResourceModel.Builder(resourceModel.getRootResources(), false);
+ final Resource singletonResource = Resource.from(SingletonResource.class);
+ builder.addResource(singletonResource);
+
+ final Resource requestScopeResource = Resource.from(RequestScopeResource.class);
+ builder.addResource(requestScopeResource);
+
+ final Resource.Builder resourceBuilder = Resource.builder("instance");
+ resourceBuilder.addMethod("GET").handledBy(new SimpleModelProcessorInflector());
+ final Resource instanceResource = resourceBuilder.build();
+
+ builder.addResource(instanceResource);
+
+ return builder.build();
+ }
+
+ @Override
+ public ResourceModel processSubResource(ResourceModel subResource, Configuration configuration) {
+ final Resource resource = Resource.builder()
+ .mergeWith(Resource.from(EnhancedSubResourceSingleton.class))
+ .mergeWith(Resource.from(EnhancedSubResource.class))
+ .mergeWith(subResource.getResources().get(0)).build();
+
+ return new ResourceModel.Builder(true).addResource(resource).build();
+ }
+
+ @Priority(5000)
+ private static class SimpleModelProcessorInflector implements Inflector<ContainerRequestContext, String> {
+ private int counter = 0;
+
+ @Override
+ public String apply(ContainerRequestContext containerRequestContext) {
+ return String.valueOf("Inflector:" + counter++);
+ }
+ }
+ }
+
+ @Singleton
+ public static class EnhancedSubResourceSingleton {
+ private int counter = 0;
+
+ @GET
+ @Path("enhanced-singleton")
+ public String get() {
+ return "EnhancedSubResourceSingleton:" + String.valueOf(counter++);
+ }
+ }
+
+ @RequestScoped
+ public static class EnhancedSubResource {
+
+ private int counter = 0;
+
+ @GET
+ @Path("enhanced")
+ public String get() {
+ return String.valueOf("EnhancedSubResource:" + counter++);
+ }
+ }
+
+ @Path("request-scope")
+ public static class RequestScopeResource {
+ private int counter = 0;
+
+ @GET
+ public String get() {
+ return String.valueOf("RequestScopeResource:" + counter++);
+ }
+ }
+
+ @Path("singleton")
+ @Singleton
+ public static class SingletonResource {
+ private int counter = 0;
+
+ @GET
+ public String get() {
+ return String.valueOf("SingletonResource:" + counter++);
+ }
+ }
+}
diff --git a/tests/e2e-inject/cdi-inject-weld/src/main/java/org/glassfish/jersey/tests/e2e/inject/cdi/weld/subresources/MyBean.java b/tests/e2e-inject/cdi-inject-weld/src/main/java/org/glassfish/jersey/tests/e2e/inject/cdi/weld/subresources/MyBean.java
new file mode 100644
index 0000000..29127df
--- /dev/null
+++ b/tests/e2e-inject/cdi-inject-weld/src/main/java/org/glassfish/jersey/tests/e2e/inject/cdi/weld/subresources/MyBean.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2021 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.inject.cdi.weld.subresources;
+
+import javax.enterprise.context.ApplicationScoped;
+import javax.inject.Inject;
+import org.glassfish.jersey.tests.e2e.inject.cdi.weld.Hello;
+import org.glassfish.jersey.tests.e2e.inject.cdi.weld.NameService;
+import org.glassfish.jersey.tests.e2e.inject.cdi.weld.Secured;
+
+@ApplicationScoped
+@Secured
+public class MyBean implements Hello {
+ @Inject
+ private NameService service;
+
+ public String hello() {
+ System.out.println("mybean");
+ return "Hello " + service.getName();
+ }
+}
diff --git a/tests/e2e-inject/cdi-inject-weld/src/main/java/org/glassfish/jersey/tests/e2e/inject/cdi/weld/subresources/RootResource.java b/tests/e2e-inject/cdi-inject-weld/src/main/java/org/glassfish/jersey/tests/e2e/inject/cdi/weld/subresources/RootResource.java
new file mode 100644
index 0000000..00d4922
--- /dev/null
+++ b/tests/e2e-inject/cdi-inject-weld/src/main/java/org/glassfish/jersey/tests/e2e/inject/cdi/weld/subresources/RootResource.java
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2021 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.inject.cdi.weld.subresources;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+
+@Path("root")
+public class RootResource {
+
+ @GET
+ public String get() {
+ return "root";
+ }
+
+ @Path("sub-resource-singleton")
+ public Class<SubResourceSingleton> getSubResourceSingleton() {
+ return SubResourceSingleton.class;
+ }
+
+ @Path("sub-resource-instance")
+ public SubResourceSingleton getSubResourceSingletonInstance() {
+ return new SubResourceSingleton();
+ }
+}
diff --git a/tests/e2e-inject/cdi-inject-weld/src/main/java/org/glassfish/jersey/tests/e2e/inject/cdi/weld/subresources/RootSingletonResource.java b/tests/e2e-inject/cdi-inject-weld/src/main/java/org/glassfish/jersey/tests/e2e/inject/cdi/weld/subresources/RootSingletonResource.java
new file mode 100644
index 0000000..14b2734
--- /dev/null
+++ b/tests/e2e-inject/cdi-inject-weld/src/main/java/org/glassfish/jersey/tests/e2e/inject/cdi/weld/subresources/RootSingletonResource.java
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2021 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.inject.cdi.weld.subresources;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+
+import javax.inject.Singleton;
+
+@Path("root-singleton")
+@Singleton
+public class RootSingletonResource {
+
+ private int counter = 0;
+
+ @GET
+ public String get() {
+ return "RootSingletonResource:" + String.valueOf(counter++);
+ }
+}
diff --git a/tests/e2e-inject/cdi-inject-weld/src/main/java/org/glassfish/jersey/tests/e2e/inject/cdi/weld/subresources/SubResourceSingleton.java b/tests/e2e-inject/cdi-inject-weld/src/main/java/org/glassfish/jersey/tests/e2e/inject/cdi/weld/subresources/SubResourceSingleton.java
new file mode 100644
index 0000000..aacd442
--- /dev/null
+++ b/tests/e2e-inject/cdi-inject-weld/src/main/java/org/glassfish/jersey/tests/e2e/inject/cdi/weld/subresources/SubResourceSingleton.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2021 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.inject.cdi.weld.subresources;
+
+import javax.ws.rs.GET;
+
+import javax.inject.Singleton;
+
+@Singleton
+public class SubResourceSingleton {
+
+ private int counter = 0;
+
+ @GET
+ public String get() {
+ return String.valueOf("SubResourceSingleton:" + counter++);
+ }
+}
diff --git a/tests/e2e-inject/cdi-inject-weld/src/main/resources/META-INF/beans.xml b/tests/e2e-inject/cdi-inject-weld/src/main/resources/META-INF/beans.xml
new file mode 100644
index 0000000..ee4acc6
--- /dev/null
+++ b/tests/e2e-inject/cdi-inject-weld/src/main/resources/META-INF/beans.xml
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ Copyright (c) 2021 Oracle and/or its affiliates. All rights reserved.
+
+ This program and the accompanying materials are made available under the
+ terms of the Eclipse Public License v. 2.0, which is available at
+ http://www.eclipse.org/legal/epl-2.0.
+
+ This Source Code may also be made available under the following Secondary
+ Licenses when the conditions for such availability set forth in the
+ Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ version 2 with the GNU Classpath Exception, which is available at
+ https://www.gnu.org/software/classpath/license.html.
+
+ SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+
+-->
+
+<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xmlns="http://xmlns.jcp.org/xml/ns/javaee"
+ xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee
+ http://xmlns.jcp.org/xml/ns/javaee/beans_2_0.xsd"
+ bean-discovery-mode="all">
+ <interceptors>
+ <class>org.glassfish.jersey.tests.e2e.inject.cdi.weld.SecurityInterceptor</class>
+ </interceptors>
+ <decorators>
+ <class>org.glassfish.jersey.tests.e2e.inject.cdi.weld.HelloStarDecorator</class>
+ </decorators>
+</beans>
diff --git a/tests/e2e-inject/cdi-inject-weld/src/test/java/org/glassfish/jersey/tests/e2e/inject/cdi/weld/EventsTest.java b/tests/e2e-inject/cdi-inject-weld/src/test/java/org/glassfish/jersey/tests/e2e/inject/cdi/weld/EventsTest.java
new file mode 100644
index 0000000..4c0cb29
--- /dev/null
+++ b/tests/e2e-inject/cdi-inject-weld/src/test/java/org/glassfish/jersey/tests/e2e/inject/cdi/weld/EventsTest.java
@@ -0,0 +1,80 @@
+/*
+ * Copyright (c) 2021 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.inject.cdi.weld;
+
+import javax.ws.rs.client.Entity;
+import javax.ws.rs.core.Application;
+import javax.ws.rs.core.Response;
+
+import org.glassfish.jersey.inject.hk2.Hk2InjectionManagerFactory;
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.test.JerseyTest;
+
+import org.jboss.weld.environment.se.Weld;
+import org.junit.Assume;
+import org.junit.Before;
+import org.junit.Test;
+import static org.junit.Assert.assertEquals;
+
+/**
+ * Tests that the resource can fire an event.
+ *
+ * @author Petr Bouda
+ */
+public class EventsTest extends JerseyTest {
+
+ private Weld weld;
+
+ @Before
+ public void setup() {
+ Assume.assumeTrue(Hk2InjectionManagerFactory.isImmediateStrategy());
+ }
+
+ @Override
+ public void setUp() throws Exception {
+ if (Hk2InjectionManagerFactory.isImmediateStrategy()) {
+ weld = new Weld();
+ weld.initialize();
+ super.setUp();
+ }
+ }
+
+ @Override
+ public void tearDown() throws Exception {
+ if (Hk2InjectionManagerFactory.isImmediateStrategy()) {
+ weld.shutdown();
+ super.tearDown();
+ }
+ }
+
+ @Override
+ protected Application configure() {
+ return new ResourceConfig(AccountResource.class);
+ }
+
+ @Test
+ public void testFiredEvents() {
+ Response credit = target("account").queryParam("amount", 50).request().post(Entity.json(""));
+ assertEquals(204, credit.getStatus());
+
+ Response debit = target("account").queryParam("amount", 25).request().delete();
+ assertEquals(204, debit.getStatus());
+
+ Long current = target("account").queryParam("amount", 25).request().get(Long.class);
+ assertEquals(25, current.longValue());
+ }
+}
diff --git a/tests/e2e-inject/cdi-inject-weld/src/test/java/org/glassfish/jersey/tests/e2e/inject/cdi/weld/InterceptorDecoratorTest.java b/tests/e2e-inject/cdi-inject-weld/src/test/java/org/glassfish/jersey/tests/e2e/inject/cdi/weld/InterceptorDecoratorTest.java
new file mode 100644
index 0000000..a7752bd
--- /dev/null
+++ b/tests/e2e-inject/cdi-inject-weld/src/test/java/org/glassfish/jersey/tests/e2e/inject/cdi/weld/InterceptorDecoratorTest.java
@@ -0,0 +1,79 @@
+/*
+ * Copyright (c) 2021 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.inject.cdi.weld;
+
+import javax.ws.rs.core.Application;
+import javax.ws.rs.core.Response;
+
+import org.glassfish.jersey.inject.hk2.Hk2InjectionManagerFactory;
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.test.JerseyTest;
+
+import org.jboss.weld.environment.se.Weld;
+import org.junit.Assume;
+import org.junit.Before;
+import org.junit.Test;
+import static org.junit.Assert.assertEquals;
+
+/**
+ * Tests that the resource can be intercepted and decorated.
+ *
+ * @author Petr Bouda
+ */
+public class InterceptorDecoratorTest extends JerseyTest {
+
+ private Weld weld;
+
+ @Before
+ public void setup() {
+ Assume.assumeTrue(Hk2InjectionManagerFactory.isImmediateStrategy());
+ }
+
+ @Override
+ public void setUp() throws Exception {
+ if (Hk2InjectionManagerFactory.isImmediateStrategy()) {
+ weld = new Weld();
+ weld.initialize();
+ super.setUp();
+ }
+ }
+
+ @Override
+ public void tearDown() throws Exception {
+ if (Hk2InjectionManagerFactory.isImmediateStrategy()) {
+ weld.shutdown();
+ super.tearDown();
+ }
+ }
+
+ @Override
+ protected Application configure() {
+ return new ResourceConfig(HelloResource.class);
+ }
+
+ @Test
+ public void testInterceptedGet() {
+ String intercepted = target("intercepted").queryParam("user", NameService.NAME).request().get(String.class);
+ assertEquals("***Hello James***", intercepted);
+ }
+
+ @Test
+ public void testForbiddenGet() {
+ Response result = target("intercepted").queryParam("user", "unknown").request().get();
+ assertEquals(403, result.getStatus());
+ }
+}
diff --git a/tests/e2e-inject/cdi-inject-weld/src/test/java/org/glassfish/jersey/tests/e2e/inject/cdi/weld/RequestContextBuilder.java b/tests/e2e-inject/cdi-inject-weld/src/test/java/org/glassfish/jersey/tests/e2e/inject/cdi/weld/RequestContextBuilder.java
new file mode 100644
index 0000000..d4cc5c5
--- /dev/null
+++ b/tests/e2e-inject/cdi-inject-weld/src/test/java/org/glassfish/jersey/tests/e2e/inject/cdi/weld/RequestContextBuilder.java
@@ -0,0 +1,206 @@
+/*
+ * Copyright (c) 2021 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.inject.cdi.weld;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.lang.annotation.Annotation;
+import java.net.URI;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+import javax.ws.rs.WebApplicationException;
+import javax.ws.rs.core.Cookie;
+import javax.ws.rs.core.GenericEntity;
+import javax.ws.rs.core.GenericType;
+import javax.ws.rs.core.HttpHeaders;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.MultivaluedHashMap;
+import javax.ws.rs.core.MultivaluedMap;
+import javax.ws.rs.core.SecurityContext;
+import javax.ws.rs.ext.WriterInterceptor;
+
+import org.glassfish.jersey.internal.MapPropertiesDelegate;
+import org.glassfish.jersey.internal.PropertiesDelegate;
+import org.glassfish.jersey.message.MessageBodyWorkers;
+import org.glassfish.jersey.message.internal.HeaderUtils;
+import org.glassfish.jersey.server.ContainerRequest;
+
+/**
+ * Used by tests to create mock JerseyContainerRequestContext instances.
+ *
+ * @author Martin Matula
+ */
+public class RequestContextBuilder {
+
+ public class TestContainerRequest extends ContainerRequest {
+
+ private Object entity;
+ private GenericType entityType;
+ private final PropertiesDelegate propertiesDelegate;
+
+ public TestContainerRequest(final URI baseUri,
+ final URI requestUri,
+ final String method,
+ final SecurityContext securityContext,
+ final PropertiesDelegate propertiesDelegate) {
+ super(baseUri, requestUri, method, securityContext, propertiesDelegate, null);
+ this.propertiesDelegate = propertiesDelegate;
+ }
+
+ public void setEntity(final Object entity) {
+ if (entity instanceof GenericEntity) {
+ this.entity = ((GenericEntity) entity).getEntity();
+ this.entityType = new GenericType(((GenericEntity) entity).getType());
+ } else {
+ this.entity = entity;
+ this.entityType = new GenericType(entity.getClass());
+ }
+ }
+
+ @Override
+ public void setWorkers(final MessageBodyWorkers workers) {
+ super.setWorkers(workers);
+ final byte[] entityBytes;
+ if (entity != null) {
+ final MultivaluedMap<String, Object> myMap = new MultivaluedHashMap<String, Object>(getHeaders());
+ final ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ OutputStream stream = null;
+ try {
+ stream = workers.writeTo(entity, entity.getClass(), entityType.getType(),
+ new Annotation[0], getMediaType(),
+ myMap,
+ propertiesDelegate, baos, Collections.<WriterInterceptor>emptyList());
+ } catch (final IOException | WebApplicationException ex) {
+ Logger.getLogger(TestContainerRequest.class.getName()).log(Level.SEVERE, null, ex);
+ } finally {
+ if (stream != null) {
+ try {
+ stream.close();
+ } catch (final IOException e) {
+ // ignore
+ }
+ }
+ }
+ entityBytes = baos.toByteArray();
+ } else {
+ entityBytes = new byte[0];
+ }
+ setEntityStream(new ByteArrayInputStream(entityBytes));
+ }
+ }
+
+ private final TestContainerRequest request;
+
+ public static RequestContextBuilder from(final String requestUri, final String method) {
+ return from(null, requestUri, method);
+ }
+
+ public static RequestContextBuilder from(final String baseUri, final String requestUri, final String method) {
+ return new RequestContextBuilder(baseUri, requestUri, method);
+ }
+
+ public static RequestContextBuilder from(final URI requestUri, final String method) {
+ return from(null, requestUri, method);
+ }
+
+ public static RequestContextBuilder from(final URI baseUri, final URI requestUri, final String method) {
+ return new RequestContextBuilder(baseUri, requestUri, method);
+ }
+
+ private RequestContextBuilder(final String baseUri, final String requestUri, final String method) {
+ this(baseUri == null || baseUri.isEmpty() ? null : URI.create(baseUri), URI.create(requestUri), method);
+ }
+
+ private RequestContextBuilder(final URI baseUri, final URI requestUri, final String method) {
+ request = new TestContainerRequest(baseUri, requestUri, method, null,
+ new MapPropertiesDelegate());
+ }
+
+ public ContainerRequest build() {
+ return request;
+ }
+
+ public RequestContextBuilder accept(final String... acceptHeader) {
+ putHeaders(HttpHeaders.ACCEPT, acceptHeader);
+ return this;
+ }
+
+ public RequestContextBuilder accept(final MediaType... acceptHeader) {
+ putHeaders(HttpHeaders.ACCEPT, (Object[]) acceptHeader);
+ return this;
+ }
+
+ public RequestContextBuilder entity(final Object entity) {
+ request.setEntity(entity);
+ return this;
+ }
+
+ public RequestContextBuilder type(final String contentType) {
+ request.getHeaders().putSingle(HttpHeaders.CONTENT_TYPE, contentType);
+ return this;
+
+ }
+
+ public RequestContextBuilder type(final MediaType contentType) {
+ request.getHeaders().putSingle(HttpHeaders.CONTENT_TYPE, HeaderUtils.asString(contentType, request.getConfiguration()));
+ return this;
+ }
+
+ public RequestContextBuilder header(final String name, final Object value) {
+ putHeader(name, value);
+ return this;
+ }
+
+ public RequestContextBuilder cookie(final Cookie cookie) {
+ putHeader(HttpHeaders.COOKIE, cookie);
+ return this;
+ }
+
+ public RequestContextBuilder cookies(final Cookie... cookies) {
+ putHeaders(HttpHeaders.COOKIE, (Object[]) cookies);
+ return this;
+ }
+
+ private void putHeader(final String name, final Object value) {
+ if (value == null) {
+ request.getHeaders().remove(name);
+ return;
+ }
+ request.header(name, HeaderUtils.asString(value, request.getConfiguration()));
+ }
+
+ private void putHeaders(final String name, final Object... values) {
+ if (values == null) {
+ request.getHeaders().remove(name);
+ return;
+ }
+ request.getHeaders().addAll(name, HeaderUtils.asStringList(Arrays.asList(values), request.getConfiguration()));
+ }
+
+ private void putHeaders(final String name, final String... values) {
+ if (values == null) {
+ request.getHeaders().remove(name);
+ return;
+ }
+ request.getHeaders().addAll(name, values);
+ }
+}
diff --git a/tests/e2e-inject/cdi-inject-weld/src/test/java/org/glassfish/jersey/tests/e2e/inject/cdi/weld/scopes/ScopesTest.java b/tests/e2e-inject/cdi-inject-weld/src/test/java/org/glassfish/jersey/tests/e2e/inject/cdi/weld/scopes/ScopesTest.java
new file mode 100644
index 0000000..9f7522b
--- /dev/null
+++ b/tests/e2e-inject/cdi-inject-weld/src/test/java/org/glassfish/jersey/tests/e2e/inject/cdi/weld/scopes/ScopesTest.java
@@ -0,0 +1,77 @@
+/*
+ * Copyright (c) 2021 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.inject.cdi.weld.scopes;
+
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.test.JerseyTest;
+
+import org.jboss.weld.environment.se.Weld;
+import org.junit.Test;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotEquals;
+
+/**
+ * Tests CDI resources.
+ */
+public class ScopesTest extends JerseyTest {
+
+ private Weld weld;
+
+ @Override
+ public void setUp() throws Exception {
+ weld = new Weld();
+ weld.initialize();
+ super.setUp();
+ }
+
+ @Override
+ public void tearDown() throws Exception {
+ weld.shutdown();
+ super.tearDown();
+ }
+
+ @Override
+ protected ResourceConfig configure() {
+ return new ResourceConfig(RequestScopedResource.class, SingletonScopedResource.class);
+ }
+
+ @Test
+ public void testCheckRequest() throws InterruptedException {
+ String[] response1 = target().path("request").path("James").request().get(String.class).split(" ");
+ String[] response2 = target().path("request").path("Marcus").request().get(String.class).split(" ");
+ assertResponses("request", response1, response2);
+ assertNotEquals(response1[3], response2[3]);
+ }
+
+ @Test
+ public void testCheckSingleton() throws InterruptedException {
+ String[] response1 = target().path("singleton").path("James").request().get(String.class).split(" ");
+ String[] response2 = target().path("singleton").path("Marcus").request().get(String.class).split(" ");
+ assertResponses("singleton", response1, response2);
+ assertEquals(response1[3], response2[3]);
+ }
+
+ private void assertResponses(String type, String[] response1, String[] response2) {
+ assertEquals("Hello_James", response1[0]);
+ assertEquals("[1]", response1[1]);
+ assertEquals("[" + type + "/James]", response1[2]);
+
+ assertEquals("Hello_Marcus", response2[0]);
+ assertEquals("[2]", response2[1]);
+ assertEquals("[" + type + "/Marcus]", response2[2]);
+ }
+}
diff --git a/tests/e2e-inject/cdi-inject-weld/src/test/java/org/glassfish/jersey/tests/e2e/inject/cdi/weld/subresources/ModelProcessorScopeTest.java b/tests/e2e-inject/cdi-inject-weld/src/test/java/org/glassfish/jersey/tests/e2e/inject/cdi/weld/subresources/ModelProcessorScopeTest.java
new file mode 100644
index 0000000..a26cb29
--- /dev/null
+++ b/tests/e2e-inject/cdi-inject-weld/src/test/java/org/glassfish/jersey/tests/e2e/inject/cdi/weld/subresources/ModelProcessorScopeTest.java
@@ -0,0 +1,140 @@
+/*
+ * Copyright (c) 2021 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.inject.cdi.weld.subresources;
+
+import java.util.concurrent.ExecutionException;
+
+import org.glassfish.jersey.server.ApplicationHandler;
+import org.glassfish.jersey.server.ContainerResponse;
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.server.ServerProperties;
+import org.glassfish.jersey.tests.e2e.inject.cdi.weld.RequestContextBuilder;
+
+import org.jboss.weld.environment.se.Weld;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import static org.junit.Assert.assertEquals;
+
+/**
+ * Test scope of resources enhanced by model processors.
+ *
+ * @author Miroslav Fuksa
+ *
+ */
+public class ModelProcessorScopeTest {
+
+ private Weld weld;
+
+ @Before
+ public void setUp() throws Exception {
+ weld = new Weld();
+ weld.initialize();
+ }
+
+ @After
+ public void tearDown() throws Exception {
+ weld.shutdown();
+ }
+
+ private void _testCounter(ApplicationHandler applicationHandler, String requestUri, final String prefix,
+ final String expectedSecondHit) throws
+ InterruptedException, ExecutionException {
+ ContainerResponse response = applicationHandler.apply(RequestContextBuilder.from(requestUri,
+ "GET").build()).get();
+ assertEquals(200, response.getStatus());
+ assertEquals(prefix + ":0", response.getEntity());
+ response = applicationHandler.apply(RequestContextBuilder.from(requestUri,
+ "GET").build()).get();
+ assertEquals(prefix + ":" + expectedSecondHit, response.getEntity());
+ }
+
+ @Test
+ public void testSingleton() throws ExecutionException, InterruptedException {
+ ApplicationHandler applicationHandler = new ApplicationHandler(new ResourceConfig(ModelProcessorFeature
+ .SingletonResource.class));
+ final String requestUri = "/singleton";
+ _testCounter(applicationHandler, requestUri, "SingletonResource", "1");
+ }
+
+ @Test
+ public void testSingletonInModelProcessor() throws ExecutionException, InterruptedException {
+ ApplicationHandler applicationHandler = new ApplicationHandler(new ResourceConfig(RootResource.class,
+ ModelProcessorFeature.class));
+ final String requestUri = "/singleton";
+ _testCounter(applicationHandler, requestUri, "SingletonResource", "1");
+ }
+
+ @Test
+ public void testSubResourceSingletonInOriginalModel() throws ExecutionException, InterruptedException {
+ ApplicationHandler applicationHandler = new ApplicationHandler(new ResourceConfig(RootResource.class));
+ final String requestUri = "/root/sub-resource-singleton";
+ _testCounter(applicationHandler, requestUri, "SubResourceSingleton", "1");
+ }
+
+ @Test
+ public void testSubResourceEnhancedSingleton() throws ExecutionException, InterruptedException {
+ ApplicationHandler applicationHandler = new ApplicationHandler(new ResourceConfig(RootResource.class));
+ final String requestUri = "/root/sub-resource-singleton/enhanced-singleton";
+ _testCounter(applicationHandler, requestUri, "EnhancedSubResourceSingleton", "1");
+ }
+
+ @Test
+ public void testSubResourceInstanceEnhancedSingleton() throws ExecutionException, InterruptedException {
+ ApplicationHandler applicationHandler = new ApplicationHandler(new ResourceConfig(RootResource.class));
+ final String requestUri = "/root/sub-resource-instance/enhanced-singleton";
+ _testCounter(applicationHandler, requestUri, "EnhancedSubResourceSingleton", "1");
+ }
+
+ @Test
+ public void testSubResourceInstanceEnhancedSubResource() throws ExecutionException, InterruptedException {
+ ApplicationHandler applicationHandler = new ApplicationHandler(new ResourceConfig(RootResource.class));
+ final String requestUri = "/root/sub-resource-instance/enhanced";
+ _testCounter(applicationHandler, requestUri, "EnhancedSubResource", "0");
+ }
+
+ @Test
+ public void testSubResourceEnhancedSubResource() throws ExecutionException, InterruptedException {
+ ApplicationHandler applicationHandler = new ApplicationHandler(new ResourceConfig(RootResource.class));
+ final String requestUri = "/root/sub-resource-singleton/enhanced";
+ _testCounter(applicationHandler, requestUri, "EnhancedSubResource", "0");
+ }
+
+ @Test
+ public void testInstanceInModelProcessor() throws ExecutionException, InterruptedException {
+ ApplicationHandler applicationHandler = new ApplicationHandler(new ResourceConfig(RootResource.class,
+ ModelProcessorFeature.class));
+ final String requestUri = "/instance";
+ _testCounter(applicationHandler, requestUri, "Inflector", "1");
+ }
+
+ @Test
+ public void testRootSingleton() throws ExecutionException, InterruptedException {
+ ApplicationHandler applicationHandler = new ApplicationHandler(new ResourceConfig(RootResource.class,
+ RootSingletonResource.class));
+ final String requestUri = "/root-singleton";
+ _testCounter(applicationHandler, requestUri, "RootSingletonResource", "1");
+ }
+
+ @Test
+ public void testRequestScopeResource() throws ExecutionException, InterruptedException {
+ ApplicationHandler applicationHandler = new ApplicationHandler(new ResourceConfig(RootResource.class,
+ RootSingletonResource.class, ModelProcessorFeature.class));
+ final String requestUri = "/request-scope";
+ _testCounter(applicationHandler, requestUri, "RequestScopeResource", "0");
+ }
+}
diff --git a/tests/e2e-inject/cdi-inject-weld/src/test/resources/surefire.policy b/tests/e2e-inject/cdi-inject-weld/src/test/resources/surefire.policy
new file mode 100644
index 0000000..a6cc723
--- /dev/null
+++ b/tests/e2e-inject/cdi-inject-weld/src/test/resources/surefire.policy
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2021 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+// we do not care about java lib itself
+grant codebase "file:${java.home}/-" {
+ permission java.security.AllPermission;
+};
+
+// we do not care about our dependencies
+grant codebase "file:${settings.localRepository}/-" {
+ permission java.security.AllPermission;
+};
+
+// this is to be able to set runtime delegate instance in jax-rs from the tests
+// and to run multi-threaded tests
+grant codebase "file:${project.build.directory}/test-classes/-" {
+ permission java.lang.reflect.ReflectPermission "suppressAccessChecks";
+ permission java.lang.RuntimePermission "modifyThread";
+ permission java.util.PropertyPermission "*", "write";
+ permission java.lang.RuntimePermission "getClassLoader";
+ permission java.lang.RuntimePermission "accessClassInPackage.sun.misc";
+ permission java.lang.RuntimePermission "accessClassInPackage.sun.misc.*";
+ permission java.lang.reflect.ReflectPermission "suppressAccessChecks";
+};
+
+grant codebase "file:${project.build.directory}/classes/-" {
+ permission java.lang.RuntimePermission "accessClassInPackage.sun.misc";
+ permission java.lang.RuntimePermission "accessDeclaredMembers";
+ permission java.lang.RuntimePermission "getClassLoader";
+ permission java.lang.RuntimePermission "modifyThread";
+ permission java.util.PropertyPermission "*", "read";
+ permission java.io.FilePermission "<<ALL FILES>>", "read";
+ permission java.lang.RuntimePermission "accessClassInPackage.sun.misc";
+ permission java.lang.RuntimePermission "accessClassInPackage.sun.misc.*";
+ permission java.lang.reflect.ReflectPermission "suppressAccessChecks";
+};
diff --git a/tests/e2e-inject/pom.xml b/tests/e2e-inject/pom.xml
index 142e17b..adab97d 100644
--- a/tests/e2e-inject/pom.xml
+++ b/tests/e2e-inject/pom.xml
@@ -34,6 +34,7 @@
<modules>
<module>cdi2-se</module>
+ <module>cdi-inject-weld</module>
<module>hk2</module>
</modules>
</project>
diff --git a/tests/integration/cdi-integration/context-inject-on-server/pom.xml b/tests/integration/cdi-integration/context-inject-on-server/pom.xml
index 38b31ca..f405087 100644
--- a/tests/integration/cdi-integration/context-inject-on-server/pom.xml
+++ b/tests/integration/cdi-integration/context-inject-on-server/pom.xml
@@ -57,24 +57,11 @@
<scope>test</scope>
</dependency>
<dependency>
- <groupId>org.glassfish.jersey.ext.cdi</groupId>
- <artifactId>jersey-weld2-se</artifactId>
- <scope>test</scope>
- </dependency>
- <dependency>
<groupId>org.jboss.weld.se</groupId>
<artifactId>weld-se-core</artifactId>
<scope>test</scope>
</dependency>
- <dependency>
- <groupId>org.glassfish.jersey.ext.cdi</groupId>
- <artifactId>jersey-cdi1x</artifactId>
- </dependency>
- <dependency>
- <groupId>org.glassfish.jersey.ext.cdi</groupId>
- <artifactId>jersey-cdi-rs-inject</artifactId>
- </dependency>
- <dependency>
+ <dependency>
<groupId>org.glassfish.jersey.media</groupId>
<artifactId>jersey-media-sse</artifactId>
</dependency>
@@ -83,4 +70,54 @@
<artifactId>jersey-container-servlet-core</artifactId>
</dependency>
</dependencies>
+ <profiles>
+ <profile>
+ <id>DefaultInject</id>
+ <activation>
+ <property><name>!cdiInject</name></property>
+ </activation>
+ <dependencies>
+ <dependency>
+ <groupId>org.glassfish.jersey.ext.cdi</groupId>
+ <artifactId>jersey-weld2-se</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.glassfish.jersey.ext.cdi</groupId>
+ <artifactId>jersey-cdi1x</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.glassfish.jersey.ext.cdi</groupId>
+ <artifactId>jersey-cdi-rs-inject</artifactId>
+ </dependency>
+ </dependencies>
+ </profile>
+ <profile>
+ <id>CdiInjectWeld</id>
+ <activation>
+ <property><name>cdiInject</name></property>
+ </activation>
+ <dependencies>
+ <dependency>
+ <groupId>org.glassfish.jersey.incubator</groupId>
+ <artifactId>jersey-cdi-inject-weld</artifactId>
+ <version>${project.version}</version>
+ <scope>test</scope>
+ </dependency>
+ </dependencies>
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-compiler-plugin</artifactId>
+ <configuration>
+ <testIncludes>
+ <testInclude>org/glassfish/jersey/tests/cdi/inject/ScopedInjectionTest.java</testInclude>
+ </testIncludes>
+ </configuration>
+ </plugin>
+ </plugins>
+ </build>
+ </profile>
+ </profiles>
</project>
diff --git a/tests/integration/cdi-integration/context-inject-on-server/src/main/java/org/glassfish/jersey/tests/cdi/inject/ApplicationInjectParent.java b/tests/integration/cdi-integration/context-inject-on-server/src/main/java/org/glassfish/jersey/tests/cdi/inject/ApplicationInjectParent.java
index fc6894a..5b4de38 100644
--- a/tests/integration/cdi-integration/context-inject-on-server/src/main/java/org/glassfish/jersey/tests/cdi/inject/ApplicationInjectParent.java
+++ b/tests/integration/cdi-integration/context-inject-on-server/src/main/java/org/glassfish/jersey/tests/cdi/inject/ApplicationInjectParent.java
@@ -51,11 +51,11 @@
@Inject
protected HttpHeaders injectHttpHeaders;
- @Context
- ParamConverterProvider contextParamConverterProvider;
-
- @Inject
- ParamConverterProvider injectParamConverterProvider;
+// @Context
+// ParamConverterProvider contextParamConverterProvider;
+//
+// @Inject
+// ParamConverterProvider injectParamConverterProvider;
@Context
protected Providers contextProviders;
diff --git a/tests/integration/cdi-integration/context-inject-on-server/src/main/java/org/glassfish/jersey/tests/cdi/inject/ParentContainerRequestFilter.java b/tests/integration/cdi-integration/context-inject-on-server/src/main/java/org/glassfish/jersey/tests/cdi/inject/ParentContainerRequestFilter.java
index a326454..75a8ccb 100644
--- a/tests/integration/cdi-integration/context-inject-on-server/src/main/java/org/glassfish/jersey/tests/cdi/inject/ParentContainerRequestFilter.java
+++ b/tests/integration/cdi-integration/context-inject-on-server/src/main/java/org/glassfish/jersey/tests/cdi/inject/ParentContainerRequestFilter.java
@@ -28,11 +28,11 @@
StringBuilder stringBuilder = new StringBuilder();
boolean injected = false;
- if (requestContext.getUriInfo().getRequestUri().toASCIIString().contains("injected")) {
+ if (requestContext.getUriInfo().getRequestUri().toASCIIString().contains("inject")) {
injected = checkInjected(stringBuilder);
}
- if (requestContext.getUriInfo().getRequestUri().toASCIIString().contains("contexted")) {
+ if (requestContext.getUriInfo().getRequestUri().toASCIIString().contains("context")) {
injected = checkContexted(stringBuilder);
}
diff --git a/tests/integration/cdi-integration/context-inject-on-server/src/main/java/org/glassfish/jersey/tests/cdi/inject/ParentContainerResponseFilter.java b/tests/integration/cdi-integration/context-inject-on-server/src/main/java/org/glassfish/jersey/tests/cdi/inject/ParentContainerResponseFilter.java
index 585f045..47a9afc 100644
--- a/tests/integration/cdi-integration/context-inject-on-server/src/main/java/org/glassfish/jersey/tests/cdi/inject/ParentContainerResponseFilter.java
+++ b/tests/integration/cdi-integration/context-inject-on-server/src/main/java/org/glassfish/jersey/tests/cdi/inject/ParentContainerResponseFilter.java
@@ -28,11 +28,11 @@
StringBuilder stringBuilder = new StringBuilder();
boolean injected = false;
- if (requestContext.getUriInfo().getRequestUri().toASCIIString().contains("injected")) {
+ if (requestContext.getUriInfo().getRequestUri().toASCIIString().contains("inject")) {
injected = checkInjected(stringBuilder);
}
- if (requestContext.getUriInfo().getRequestUri().toASCIIString().contains("contexted")) {
+ if (requestContext.getUriInfo().getRequestUri().toASCIIString().contains("context")) {
injected = checkContexted(stringBuilder);
}
diff --git a/tests/integration/cdi-integration/context-inject-on-server/src/main/java/org/glassfish/jersey/tests/cdi/inject/ParentInject.java b/tests/integration/cdi-integration/context-inject-on-server/src/main/java/org/glassfish/jersey/tests/cdi/inject/ParentInject.java
index 29e11d8..6a546fb 100644
--- a/tests/integration/cdi-integration/context-inject-on-server/src/main/java/org/glassfish/jersey/tests/cdi/inject/ParentInject.java
+++ b/tests/integration/cdi-integration/context-inject-on-server/src/main/java/org/glassfish/jersey/tests/cdi/inject/ParentInject.java
@@ -55,11 +55,11 @@
@Inject
protected HttpHeaders injectHttpHeaders;
- @Context
- protected ParamConverterProvider contextParamConverterProvider;
-
- @Inject
- protected ParamConverterProvider injectParamConverterProvider;
+// @Context
+// protected ParamConverterProvider contextParamConverterProvider;
+//
+// @Inject
+// protected ParamConverterProvider injectParamConverterProvider;
@Context
protected PropertiesDelegate contextPropertiesDelegate;
@@ -140,7 +140,7 @@
injected &= checkConfiguration(injectConfiguration, stringBuilder);
injected &= InjectionChecker.checkHttpHeaders(injectHttpHeaders, stringBuilder);
injected &= checkPropertiesDelegate(injectPropertiesDelegate, stringBuilder);
- injected &= InjectionChecker.checkParamConverterProvider(injectParamConverterProvider, stringBuilder);
+// injected &= InjectionChecker.checkParamConverterProvider(injectParamConverterProvider, stringBuilder);
injected &= InjectionChecker.checkProviders(injectProviders, stringBuilder);
injected &= InjectionChecker.checkRequest(injectRequest, stringBuilder);
injected &= InjectionChecker.checkResourceContext(injectResourceContext, stringBuilder);
@@ -163,7 +163,7 @@
injected &= checkApplication(contextApplication, stringBuilder);
injected &= checkConfiguration(contextConfiguration, stringBuilder);
injected &= InjectionChecker.checkHttpHeaders(contextHttpHeaders, stringBuilder);
- injected &= InjectionChecker.checkParamConverterProvider(contextParamConverterProvider, stringBuilder);
+// injected &= InjectionChecker.checkParamConverterProvider(contextParamConverterProvider, stringBuilder);
injected &= checkPropertiesDelegate(contextPropertiesDelegate, stringBuilder);
injected &= InjectionChecker.checkProviders(contextProviders, stringBuilder);
injected &= InjectionChecker.checkRequest(contextRequest, stringBuilder);