package org.osgi.cdi.impl.extension;
import java.lang.annotation.Annotation;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
import javax.enterprise.context.ApplicationScoped;
import javax.enterprise.event.Observes;
import javax.enterprise.inject.spi.AfterBeanDiscovery;
import javax.enterprise.inject.spi.BeanManager;
import javax.enterprise.inject.spi.BeforeBeanDiscovery;
import javax.enterprise.inject.spi.Extension;
import javax.enterprise.inject.spi.InjectionPoint;
import javax.enterprise.inject.spi.ProcessBean;
import javax.enterprise.inject.spi.ProcessInjectionTarget;
import javax.enterprise.inject.spi.ProcessObserverMethod;
import org.osgi.cdi.api.extension.Service;
import org.osgi.cdi.api.extension.annotation.Filter;
import org.osgi.cdi.api.extension.annotation.OSGiService;
import org.osgi.cdi.api.extension.annotation.Required;
import org.osgi.cdi.impl.extension.services.BundleHolder;
import org.osgi.cdi.impl.extension.services.ContainerObserver;
import org.osgi.cdi.impl.extension.services.RegistrationsHolder;
import org.osgi.cdi.impl.extension.services.ServiceRegistryImpl;
import org.osgi.cdi.impl.extension.services.WeldOSGiProducer;
/**
* Weld OSGi extension.
*
* Contains copy/paste parts from the GlasFish OSGI-CDI extension.
*
* @author Mathieu ANCELIN - SERLI (mathieu.ancelin@serli.com)
*/
@ApplicationScoped
public class CDIOSGiExtension implements Extension {
// hack for weld integration
public static ThreadLocal<Long> currentBundle =
new ThreadLocal<Long>();
private HashMap<Type, Set<InjectionPoint>> servicesToBeInjected
= new HashMap<Type, Set<InjectionPoint>>();
private HashMap<Type, Set<InjectionPoint>> filteredServiceToBeInjected
= new HashMap<Type, Set<InjectionPoint>>();
private List<Annotation> observers = new ArrayList<Annotation>();
private Set<Class<?>> requiredOsgiServiceDependencies = new HashSet<Class<?>>();
public void registerWeldOSGiBeans(@Observes BeforeBeanDiscovery event, BeanManager manager) {
event.addAnnotatedType(manager.createAnnotatedType(WeldOSGiProducer.class));
event.addAnnotatedType(manager.createAnnotatedType(BundleHolder.class));
event.addAnnotatedType(manager.createAnnotatedType(RegistrationsHolder.class));
event.addAnnotatedType(manager.createAnnotatedType(ServiceRegistryImpl.class));
event.addAnnotatedType(manager.createAnnotatedType(ContainerObserver.class));
event.addQualifier(OSGiService.class);
}
public void registerWeldOSGiContexts(@Observes AfterBeanDiscovery event) {
for (Iterator<Type> iterator = this.servicesToBeInjected.keySet().iterator();
iterator.hasNext();) {
Type type = iterator.next();
if (!(type instanceof Class)) {
//XXX: need to handle Instance<Class>. This fails currently
System.out.println("Unknown type:" + type);
event.addDefinitionError(
new UnsupportedOperationException(
"Injection target type " + type + "not supported"));
break;
}
addBean(event, type, this.servicesToBeInjected.get(type));
}
for (Iterator<Type> iterator = this.filteredServiceToBeInjected.keySet().iterator();
iterator.hasNext();) {
Type type = iterator.next();
addFilteredService(event, type, this.filteredServiceToBeInjected.get(type));
}
}
public void registerObservers(@Observes ProcessObserverMethod event) {
Set<Annotation> qualifiers = event.getObserverMethod().getObservedQualifiers();
for (Annotation qualifier : qualifiers) {
if (qualifier.annotationType().equals(Filter.class)) {
observers.add(qualifier);
}
}
}
public void afterProcessInjectionTarget(@Observes ProcessInjectionTarget<?> event){
Set<InjectionPoint> injectionPoints = event.getInjectionTarget().getInjectionPoints();
discoverServiceInjectionPoints(injectionPoints);
}
public void afterProcessBean(@Observes ProcessBean event){
Set<InjectionPoint> injectionPoints = event.getBean().getInjectionPoints();
discoverServiceInjectionPoints(injectionPoints);
}
private void discoverServiceInjectionPoints(Set<InjectionPoint> injectionPoints) {
for (Iterator<InjectionPoint> iterator
= injectionPoints.iterator(); iterator.hasNext();) {
InjectionPoint injectionPoint = iterator.next();
boolean service = false;
try {
if (((ParameterizedType)injectionPoint.getType())
.getRawType().equals(Service.class)) {
service = true;
}
} catch (Exception e) {}
Set<Annotation> qualifs = injectionPoint.getQualifiers();
for (Iterator<Annotation> qualifIter = qualifs.iterator();
qualifIter.hasNext();) {
Annotation annotation = qualifIter.next();
if (annotation.annotationType().equals(OSGiService.class)){
if (contains(injectionPoint.getQualifiers(), Required.class)) {
requiredOsgiServiceDependencies.add((Class) injectionPoint.getType());
}
addServiceInjectionInfo(injectionPoint);
}
if (annotation.annotationType().equals(Filter.class)){
if (service) {
addFilteredServiceInjectionInfo(injectionPoint);
}
}
}
}
}
private void addFilteredServiceInjectionInfo(InjectionPoint injectionPoint) {
Type key = injectionPoint.getType();
if (!filteredServiceToBeInjected.containsKey(key)){
filteredServiceToBeInjected.put(key, new HashSet<InjectionPoint>());
}
filteredServiceToBeInjected.get(key).add(injectionPoint);
}
private void addServiceInjectionInfo(InjectionPoint injectionPoint) {
Type key = injectionPoint.getType();
if (!servicesToBeInjected.containsKey(key)){
servicesToBeInjected.put(key, new HashSet<InjectionPoint>());
}
servicesToBeInjected.get(key).add(injectionPoint);
}
private void addBean(
AfterBeanDiscovery event,
final Type type,
final Set<InjectionPoint> injectionPoints) {
for (Iterator<InjectionPoint> iterator
= injectionPoints.iterator(); iterator.hasNext();) {
final InjectionPoint injectionPoint = iterator.next();
event.addBean(new OSGiServiceBean(injectionPoint));
}
}
private void addFilteredService(
AfterBeanDiscovery event,
final Type type,
final Set<InjectionPoint> injectionPoints) {
for (Iterator<InjectionPoint> iterator
= injectionPoints.iterator(); iterator.hasNext();) {
final InjectionPoint injectionPoint = iterator.next();
event.addBean(new FilteredServiceBean(injectionPoint));
}
}
private boolean contains(Set<Annotation> qualifiers, Class<? extends Annotation> qualifier) {
for (Annotation annotation : qualifiers) {
if (annotation.annotationType().equals(qualifier)) {
return true;
}
}
return false;
}
public List<Annotation> getObservers() {
return observers;
}
public Set<Class<?>> getRequiredOsgiServiceDependencies() {
return requiredOsgiServiceDependencies;
}
}