package org.osgi.cdi.impl.extension.services; import java.lang.annotation.Annotation; import java.lang.reflect.Proxy; import java.lang.reflect.Type; import java.util.ArrayList; import java.util.Collections; import java.util.Iterator; import java.util.List; import javax.enterprise.inject.UnsatisfiedResolutionException; import javax.enterprise.util.TypeLiteral; import org.osgi.cdi.api.extension.Service; import org.osgi.cdi.api.extension.annotation.Filter; import org.osgi.framework.BundleContext; import org.osgi.framework.InvalidSyntaxException; import org.osgi.framework.ServiceReference; /** * * @author Mathieu ANCELIN - SERLI (mathieu.ancelin@serli.com) */ public class ServiceImpl<T> implements Service<T> { private final Class serviceClass; private final BundleContext registry; private final String serviceName; private List<T> services = new ArrayList<T>(); private T service; private Filter filter; public ServiceImpl(Type t, BundleContext registry) { serviceClass = (Class) t; serviceName = serviceClass.getName(); this.registry = registry; } public ServiceImpl(Type t, BundleContext registry, Filter filter) { serviceClass = (Class) t; serviceName = serviceClass.getName(); this.registry = registry; this.filter = filter; } @Override public T get() { if (service == null) { try { populateService(); } catch (Exception ex) { ex.printStackTrace(); } } return service; } private void populateService() throws Exception { ServiceReference ref = registry.getServiceReference(serviceName); if (ref != null) { if (!serviceClass.isInterface()) { service = (T) registry.getService(ref); } else { service = (T) Proxy.newProxyInstance( getClass().getClassLoader(), new Class[]{(Class) serviceClass}, new DynamicServiceHandler(registry.getBundle(), serviceName, filter)); } } else { throw new IllegalStateException("Can't load service from OSGi registry : " + serviceName); } } private void populateServices() throws Exception { services.clear(); String filterString = null; if (filter != null && !filter.value().equals("")) { filterString = filter.value(); } ServiceReference[] refs = registry.getServiceReferences(serviceName, filterString); if (refs != null) { for (ServiceReference ref : refs) { if (!serviceClass.isInterface()) { services.add((T) registry.getService(ref)); } else { services.add((T) Proxy.newProxyInstance( getClass().getClassLoader(), new Class[]{(Class) serviceClass}, new ServiceReferenceHandler(ref, registry))); } } } } @Override public Service<T> select(Annotation... qualifiers) { if (qualifiers == null) { throw new IllegalArgumentException("You can't pass null array of qualifiers"); } if (qualifiers.length > 1) { throw new IllegalArgumentException("You can only one OSGi Filter"); } for (Annotation qualifier : qualifiers) { if (!qualifier.annotationType().equals(Filter.class)) { throw new IllegalArgumentException("You can only use instances of Filter on OSGi Service<T>"); } } this.filter = (Filter) qualifiers[0]; return this; } @Override public <U extends T> Service<U> select(Class<U> subtype, Annotation... qualifiers) { throw new UnsatisfiedResolutionException("You can't subtype OSGi Services. The contract is the only valid type."); } @Override public <U extends T> Service<U> select(TypeLiteral<U> subtype, Annotation... qualifiers) { throw new UnsatisfiedResolutionException("You can't subtype OSGi Services. The contract is the only valid type."); } @Override public boolean isUnsatisfied() { return (size() <= 0); } @Override public boolean isAmbiguous() { return (size() > 1); } @Override public Iterator<T> iterator() { try { populateServices(); } catch (Exception ex) { ex.printStackTrace(); services = Collections.emptyList(); } return services.iterator(); } @Override public int size() { try { ServiceReference[] refs = registry.getServiceReferences(serviceName, null); if (refs == null) { return 0; } else { return refs.length; } } catch (InvalidSyntaxException ex) { return -1; } } }