![JAR search and dependency download from the Maven repository](/logo.png)
org.glassfish.jersey.inject.cdi.se.CdiSeInjectionManager Maven / Gradle / Ivy
/*
* Copyright (c) 2017, 2022 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.cdi.se;
import java.lang.annotation.Annotation;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Set;
import javax.enterprise.context.spi.CreationalContext;
import javax.enterprise.inject.se.SeContainer;
import javax.enterprise.inject.se.SeContainerInitializer;
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.InjectionTargetFactory;
import javax.enterprise.inject.spi.Unmanaged;
import org.glassfish.jersey.inject.cdi.se.bean.JerseyBean;
import org.glassfish.jersey.inject.cdi.se.injector.ContextInjectionResolverImpl;
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.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;
/**
* Implementation of {@link InjectionManager} that starts CDI SE container, scans all users bean according to beans.xml file and
* register Jersey's internal beans using {@link SeBeanRegisterExtension} extension.
*
* @author Petr Bouda
*/
public class CdiSeInjectionManager implements InjectionManager {
// Keeps all binders and bindings added to the InjectionManager during the bootstrap.
private final AbstractBinder bindings = new AbstractBinder() {
@Override
protected void configure() {
}
};
private SeContainer container;
private BeanManager beanManager;
@Override
public void register(Binding binding) {
bindings.bind(binding);
}
@Override
public void register(Iterable bindings) {
for (Binding binding : bindings) {
this.bindings.bind(binding);
}
}
@Override
public void register(Binder binder) {
for (Binding binding : Bindings.getBindings(this, binder)) {
bindings.bind(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 createAndInitialize(Class createMe) {
if (isInitialized()) {
Unmanaged.UnmanagedInstance unmanaged = new Unmanaged<>(createMe).newInstance();
return unmanaged.produce()
.inject()
.postConstruct()
.get();
} else {
// TODO: method is invoked before #completeRegistration - creates AutoDiscoverable, ForcedAutoDiscoverable.
// Hack: creates an object with default constructor and without an injection.
try {
Constructor constructor = createMe.getConstructor();
return constructor.newInstance();
} catch (NoSuchMethodException | IllegalAccessException | InstantiationException | InvocationTargetException e) {
throw new RuntimeException("Cannot create an instance of a class: " + createMe, e);
}
}
}
@Override
public T create(Class createMe) {
if (isInitialized()) {
Unmanaged.UnmanagedInstance unmanaged = new Unmanaged<>(createMe).newInstance();
return unmanaged.produce().get();
} else {
// TODO: method is invoked before #completeRegistration - creates AutoDiscoverable, ForcedAutoDiscoverable.
// Hack: creates an object with default constructor and without an injection.
try {
Constructor constructor = createMe.getConstructor();
return constructor.newInstance();
} catch (NoSuchMethodException | IllegalAccessException | InstantiationException | InvocationTargetException e) {
throw new RuntimeException("Cannot create an instance of a class: " + createMe, e);
}
}
}
@Override
@SuppressWarnings("unchecked")
public List> getAllServiceHolders(Class contractOrImpl, Annotation... qualifiers) {
List> result = new ArrayList<>();
for (Bean> bean : beanManager.getBeans(contractOrImpl, qualifiers)) {
CreationalContext> ctx = beanManager.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) bean.getBeanClass(), bean.getTypes(), rank));
}
return result;
}
@Override
public T getInstance(Class contractOrImpl, Annotation... qualifiers) {
return getInstanceInternal(contractOrImpl, qualifiers);
}
@Override
public T getInstance(Class contractOrImpl) {
return getInstanceInternal(contractOrImpl);
}
@Override
public T getInstance(Type contractOrImpl) {
return getInstanceInternal(contractOrImpl);
}
@SuppressWarnings("unchecked")
private T getInstanceInternal(Type contractOrImpl, Annotation... qualifiers) {
Set> beans = isInitialized() ? beanManager.getBeans(contractOrImpl, qualifiers) : Collections.emptySet();
if (beans.isEmpty()) {
return null;
}
Bean> bean = beans.iterator().next();
CreationalContext> ctx = beanManager.createCreationalContext(bean);
return (T) beanManager.getReference(bean, contractOrImpl, ctx);
}
/**
* checks if being invoked before #completeRegistration
* there are 2 signs for that - container is null (not initialized)
* and beanManager is null (because it appears from initialized container)
*
* @return true if completeRegistration was already invoked. False if it's not yet initialized
*/
private boolean isInitialized() {
return container != null && beanManager != null;
}
@Override
@SuppressWarnings("unchecked")
public Object getInstance(ForeignDescriptor foreignDescriptor) {
Bean bean = (Bean) foreignDescriptor.get();
CreationalContext ctx = beanManager.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> beans = beanManager.getBeans(clazz);
if (beans.isEmpty()) {
return null;
}
Bean bean = beans.iterator().next();
CreationalContext ctx = beanManager.createCreationalContext(bean);
return ForeignDescriptor.wrap(bean, instance -> bean.destroy(instance, ctx));
}
@Override
@SuppressWarnings("unchecked")
public List getAllInstances(Type contractOrImpl) {
List result = new ArrayList<>();
for (Bean> bean : beanManager.getBeans(contractOrImpl)) {
CreationalContext> ctx = beanManager.createCreationalContext(bean);
Object reference = beanManager.getReference(bean, contractOrImpl, ctx);
result.add((T) reference);
}
return result;
}
@Override
@SuppressWarnings("unchecked")
public void inject(Object instance) {
if (isInitialized()) {
CreationalContext context = beanManager.createCreationalContext(null);
AnnotatedType annotatedType = beanManager.createAnnotatedType((Class) instance.getClass());
InjectionTargetFactory injectionTargetFactory = beanManager.getInjectionTargetFactory(annotatedType);
InjectionTarget injectionTarget = injectionTargetFactory.createInjectionTarget(null);
injectionTarget.inject(instance, context);
}
}
@Override
public void preDestroy(Object preDestroyMe) {
this.container.destroy(preDestroyMe);
}
@Override
public void completeRegistration() throws IllegalStateException {
bindings.bind(Bindings.service(this).to(InjectionManager.class));
bindings.install(new ContextInjectionResolverImpl.Binder(this::getBeanManager));
SeContainerInitializer containerInitializer = SeContainerInitializer.newInstance();
containerInitializer.addExtensions(new SeBeanRegisterExtension(bindings));
this.container = containerInitializer.initialize();
this.beanManager = container.getBeanManager();
}
protected AbstractBinder getBindings() {
return bindings;
}
public SeContainer getContainer() {
return container;
}
public void setContainer(SeContainer container) {
this.container = container;
}
public BeanManager getBeanManager() {
return beanManager;
}
public void setBeanManager(BeanManager beanManager) {
this.beanManager = beanManager;
}
@Override
public void shutdown() {
if (container != null && container.isRunning()) {
container.close();
}
}
@Override
public boolean isShutdown() {
return !container.isRunning();
}
@Override
public void inject(Object injectMe, String classAnalyzer) {
// TODO: Used only in legacy CDI integration.
throw new UnsupportedOperationException();
}
@Override
public T getInstance(Class contractOrImpl, String classAnalyzer) {
// TODO: Used only in legacy CDI integration.
throw new UnsupportedOperationException();
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy