/* * Copyright 2014 Harald Wellmann * Copyright 2016 Guillaume Nodet * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or * implied. * * See the License for the specific language governing permissions and * limitations under the License. */ package org.ops4j.pax.cdi.extension.impl; import java.lang.annotation.Annotation; import javax.annotation.PostConstruct; import javax.annotation.PreDestroy; import javax.enterprise.context.ApplicationScoped; import javax.enterprise.context.Initialized; import javax.enterprise.event.Event; import javax.enterprise.event.Observes; import javax.enterprise.util.TypeLiteral; import javax.inject.Inject; import java.util.Collections; import java.util.HashMap; import java.util.Map; import org.ops4j.pax.cdi.api.event.ServiceCdiEvent; import org.ops4j.pax.cdi.extension.impl.support.Filters; import org.ops4j.pax.cdi.extension.impl.util.ParameterizedTypeLiteral; import org.ops4j.pax.cdi.extension.impl.util.ServiceAddedLiteral; import org.ops4j.pax.cdi.extension.impl.util.ServiceRemovedLiteral; import org.osgi.framework.*; /** * Maps OSGi service events to CDI events. Fires events qualified with {@code ServiceAdded} or * {@code ServiceRemoved}. * * @author Harald Wellmann * @author Guillaume Nodet * */ @ApplicationScoped public class ServiceEventBridge implements ServiceListener { @Inject private BundleContext bundleContext; @Inject private Event<Object> event; @Inject private OsgiExtension2 extension; private String filter; private Map<Annotation, Filter> filters; @SuppressWarnings({ "unchecked", "rawtypes" }) @Override public void serviceChanged(ServiceEvent serviceEvent) { Annotation qualifier = toQualifier(serviceEvent); if (qualifier == null) { return; } ServiceReference serviceReference = serviceEvent.getServiceReference(); ServiceObjects serviceObjects = bundleContext.getServiceObjects(serviceReference); Object service = serviceObjects.getService(); try { Class klass = service.getClass(); Event<Object> event = this.event; for (Map.Entry<Annotation, Filter> entry : filters.entrySet()) { if (entry.getValue().match(serviceReference)) { event = event.select(entry.getKey()); } } event.select(klass, qualifier).fire(service); TypeLiteral literal = new ParameterizedTypeLiteral(ServiceCdiEvent.class, klass); ServiceCdiEvent cdiEvent = new ServiceCdiEvent(serviceReference, service); event.select(literal, qualifier).fire(cdiEvent); } finally { serviceObjects.ungetService(service); } } @PostConstruct public void init() { filter = Filters.or(extension.getObservedFilters()); if (filter != null) { try { filters = new HashMap<>(); for (Annotation annotation : extension.getObservedQualifiers()) { String flt = Filters.getFilter(Collections.singleton(annotation)); if (flt != null) { filters.put(annotation, bundleContext.createFilter(flt)); } } bundleContext.addServiceListener(this, filter); } catch (InvalidSyntaxException e) { throw new RuntimeException(e); } } } @PreDestroy public void destroy() { if (filter != null) { bundleContext.removeServiceListener(this); } } private Annotation toQualifier(ServiceEvent serviceEvent) { switch (serviceEvent.getType()) { case ServiceEvent.REGISTERED: return new ServiceAddedLiteral(); case ServiceEvent.UNREGISTERING: return new ServiceRemovedLiteral(); default: return null; } } // Force the instantation of this bean public void applicationScopeInitialized(@Observes @Initialized(ApplicationScoped.class) Object init) { } }