package org.springframework.roo.support.osgi; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.logging.Logger; import org.osgi.framework.BundleContext; import org.osgi.framework.InvalidSyntaxException; import org.osgi.framework.ServiceReference; import org.springframework.roo.support.logging.HandlerUtils; /** * = _ServiceInstaceManager_ * * Utility class which handles OSGi service request of a Component. * * This caches previous request. * * *Warning*: This class requires to set {@link BundleContext} thru calling {@link #activate(BundleContext)} * before return service instances. * * @author Jose Manuel Vivó * @author Juan Carlos García * @since 2.0.0 */ public class ServiceInstaceManager { public interface Matcher<T> { boolean match(T service); } protected final static Logger LOGGER = HandlerUtils.getLogger(ServiceInstaceManager.class); @SuppressWarnings("rawtypes") private Map<Class, Object> instances = new HashMap<Class, Object>(8); private BundleContext context; public ServiceInstaceManager() {} public void activate(BundleContext context) { this.context = context; } @SuppressWarnings({"unchecked"}) public <SERVICE> SERVICE getServiceInstance(Object requester, Class<SERVICE> serviceClass) { SERVICE service = (SERVICE) instances.get(serviceClass); if (service == null) { if (context == null) { throw new IllegalStateException("Tried to get service '" + serviceClass.getName() + "' without activation in " + requester.getClass().getCanonicalName()); } try { ServiceReference<?>[] references = context.getAllServiceReferences(serviceClass.getName(), null); if (references == null) { LOGGER.warning("Cannot load " + serviceClass.getName() + " on " + requester.getClass().getName() + ": getAllServiceReferences returns 'null'"); return null; } if (references.length >= 1) { // XXX should store reference to support dereference instances? service = (SERVICE) context.getService(references[0]); if (references.length > 1) { LOGGER.warning("Found multiples references of " + serviceClass.getName() + " on " + requester.getClass().getName() + ": using " + service.getClass().getCanonicalName()); } } } catch (InvalidSyntaxException e) { LOGGER.warning("Cannot load " + serviceClass.getName() + " on " + requester.getClass().getName() + ":".concat(e.toString())); return null; } if (service != null) { instances.put(serviceClass, service); } } return service; } @SuppressWarnings({"unchecked"}) public <SERVICE> List<SERVICE> getServiceInstance(Object requester, Class<SERVICE> serviceClass, Matcher<SERVICE> matcher) { SERVICE service = null; if (context == null) { throw new IllegalStateException("Tried to get service '" + serviceClass.getName() + "' without activation in " + requester.getClass().getCanonicalName()); } try { ServiceReference<?>[] references = context.getAllServiceReferences(serviceClass.getName(), null); if (references == null) { LOGGER.warning("Cannot load " + serviceClass.getName() + " on " + requester.getClass().getName() + ": getAllServiceReferences returns 'null'"); return null; } List<SERVICE> matches = new ArrayList<SERVICE>(); if (references.length > 0) { for (ServiceReference<?> reference : references) { service = (SERVICE) context.getService(reference); if (matcher.match(service)) { matches.add(service); } } } if (!matches.isEmpty()) { return matches; } return null; } catch (InvalidSyntaxException e) { LOGGER.warning("Cannot load " + serviceClass.getName() + " on " + requester.getClass().getName() + ":".concat(e.toString())); return null; } } public void deactivate() { // XXX should dereference instances? instances.clear(); } }