X-Git-Url: https://git.opendaylight.org/gerrit/gitweb?a=blobdiff_plain;f=opendaylight%2Fconfig%2Fconfig-manager%2Fsrc%2Fmain%2Fjava%2Forg%2Fopendaylight%2Fcontroller%2Fconfig%2Fmanager%2Fimpl%2Fosgi%2FBeanToOsgiServiceManager.java;h=67475dacf86dde967fbf1877d5892678836a0d28;hb=4497e2212e73e13356447b9644bbdc935411949a;hp=41f577844af5ed448a322a9a21f2f410782632cd;hpb=24feaa3333de6eadfc99a63cce0f95479e3b5f96;p=controller.git diff --git a/opendaylight/config/config-manager/src/main/java/org/opendaylight/controller/config/manager/impl/osgi/BeanToOsgiServiceManager.java b/opendaylight/config/config-manager/src/main/java/org/opendaylight/controller/config/manager/impl/osgi/BeanToOsgiServiceManager.java index 41f577844a..67475dacf8 100644 --- a/opendaylight/config/config-manager/src/main/java/org/opendaylight/controller/config/manager/impl/osgi/BeanToOsgiServiceManager.java +++ b/opendaylight/config/config-manager/src/main/java/org/opendaylight/controller/config/manager/impl/osgi/BeanToOsgiServiceManager.java @@ -7,109 +7,108 @@ */ package org.opendaylight.controller.config.manager.impl.osgi; -import org.opendaylight.controller.config.api.ModuleIdentifier; -import org.opendaylight.controller.config.api.annotations.ServiceInterfaceAnnotation; -import org.opendaylight.controller.config.manager.impl.util.InterfacesHelper; -import org.opendaylight.controller.config.spi.Module; -import org.osgi.framework.BundleContext; -import org.osgi.framework.ServiceRegistration; +import static com.google.common.base.Preconditions.checkState; import java.util.Dictionary; import java.util.HashSet; import java.util.Hashtable; +import java.util.Map; +import java.util.Map.Entry; import java.util.Set; +import javax.annotation.concurrent.GuardedBy; +import org.opendaylight.controller.config.api.ModuleIdentifier; +import org.opendaylight.controller.config.api.annotations.ServiceInterfaceAnnotation; +import org.osgi.framework.BundleContext; +import org.osgi.framework.ServiceRegistration; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; /** * Registers instantiated beans as OSGi services and unregisters these services * if beans are destroyed. */ public class BeanToOsgiServiceManager { - // name of properties submitted to osgi - static final String INSTANCE_NAME_OSGI_PROP = "instanceName"; - static final String IMPLEMENTATION_NAME_OSGI_PROP = "implementationName"; + private static final String SERVICE_NAME_OSGI_PROP = "name"; /** * To be called for every created, reconfigured and recreated config bean. * It is expected that before using this method OSGi service registry will * be cleaned from previous registrations. */ - public OsgiRegistration registerToOsgi( - Class configBeanClass, AutoCloseable instance, - ModuleIdentifier moduleIdentifier, BundleContext bundleContext) { - try { - final Set> configuresInterfaces = InterfacesHelper - .getOsgiRegistrationTypes(configBeanClass); - checkInstanceImplementing(instance, configuresInterfaces); - - // bundleContext.registerService blows up with empty 'clazzes' - if (configuresInterfaces.isEmpty() == false) { - final Dictionary propertiesForOsgi = getPropertiesForOsgi(moduleIdentifier); - final ServiceRegistration serviceRegistration = bundleContext - .registerService(classesToNames(configuresInterfaces), instance, propertiesForOsgi); - return new OsgiRegistration(serviceRegistration); - } else { - return new OsgiRegistration(); - } - } catch (IllegalStateException e) { - throw new IllegalStateException( - "Error while registering instance into OSGi Service Registry: " - + moduleIdentifier, e); - } + public OsgiRegistration registerToOsgi(AutoCloseable instance, ModuleIdentifier moduleIdentifier, + BundleContext bundleContext, + Map serviceNamesToAnnotations) { + return new OsgiRegistration(instance, moduleIdentifier, bundleContext, serviceNamesToAnnotations); } - private static String[] classesToNames(Set> cfgs) { - String[] result = new String[cfgs.size()]; - int i = 0; - for (Class cfg : cfgs) { - result[i] = cfg.getName(); - i++; - } + private static Dictionary createProps(String serviceName) { + Hashtable result = new Hashtable<>(); + result.put(SERVICE_NAME_OSGI_PROP, serviceName); return result; } - private void checkInstanceImplementing(AutoCloseable instance, - Set> configures) { - Set> missing = new HashSet<>(); - for (Class requiredIfc : configures) { - if (requiredIfc.isInstance(instance) == false) { - missing.add(requiredIfc); - } - } - if (missing.isEmpty() == false) { - throw new IllegalStateException( - instance.getClass() - + " does not implement following interfaces as announced by " - + ServiceInterfaceAnnotation.class.getName() - + " annotation :" + missing); - } - } - - private static Dictionary getPropertiesForOsgi( - ModuleIdentifier moduleIdentifier) { - Hashtable table = new Hashtable<>(); - table.put(IMPLEMENTATION_NAME_OSGI_PROP, - moduleIdentifier.getFactoryName()); - table.put(INSTANCE_NAME_OSGI_PROP, moduleIdentifier.getInstanceName()); - return table; - } public static class OsgiRegistration implements AutoCloseable { - private final ServiceRegistration serviceRegistration; + private static final Logger LOG = LoggerFactory.getLogger(OsgiRegistration.class); - public OsgiRegistration(ServiceRegistration serviceRegistration) { - this.serviceRegistration = serviceRegistration; + @GuardedBy("this") + private AutoCloseable instance; + private final ModuleIdentifier moduleIdentifier; + @GuardedBy("this") + private final Set> serviceRegistrations; + @GuardedBy("this") + private final Map serviceNamesToAnnotations; + + public OsgiRegistration(AutoCloseable instance, ModuleIdentifier moduleIdentifier, + BundleContext bundleContext, + Map serviceNamesToAnnotations) { + this.instance = instance; + this.moduleIdentifier = moduleIdentifier; + this.serviceNamesToAnnotations = serviceNamesToAnnotations; + this.serviceRegistrations = registerToSR(instance, bundleContext, serviceNamesToAnnotations); } - public OsgiRegistration() { - this.serviceRegistration = null; + private static Set> registerToSR(AutoCloseable instance, BundleContext bundleContext, + Map serviceNamesToAnnotations) { + Set> serviceRegistrations = new HashSet<>(); + for (Entry entry : serviceNamesToAnnotations.entrySet()) { + Class requiredInterface = entry.getKey().osgiRegistrationType(); + checkState(requiredInterface.isInstance(instance), instance.getClass().getName() + + " instance should implement " + requiredInterface.getName()); + Dictionary propertiesForOsgi = createProps(entry.getValue()); + ServiceRegistration serviceRegistration = bundleContext + .registerService(requiredInterface.getName(), instance, propertiesForOsgi); + serviceRegistrations.add(serviceRegistration); + } + return serviceRegistrations; } @Override - public void close() { - if (serviceRegistration != null) { - serviceRegistration.unregister(); + public synchronized void close() { + for (ServiceRegistration serviceRegistration : serviceRegistrations) { + try { + serviceRegistration.unregister(); + } catch(IllegalStateException e) { + LOG.trace("Cannot unregister {}", serviceRegistration, e); + } } + serviceRegistrations.clear(); } - } + public synchronized void updateRegistrations(Map newAnnotationMapping, + BundleContext bundleContext, AutoCloseable newInstance) { + boolean notEquals = this.instance != newInstance; + notEquals |= newAnnotationMapping.equals(serviceNamesToAnnotations) == false; + if (notEquals) { + // FIXME: changing from old state to new state can be improved by computing the diff + LOG.debug("Detected change in service registrations for {}: old: {}, new: {}", moduleIdentifier, + serviceNamesToAnnotations, newAnnotationMapping); + close(); + this.instance = newInstance; + Set> newRegs = registerToSR(instance, bundleContext, newAnnotationMapping); + serviceRegistrations.clear(); + serviceRegistrations.addAll(newRegs); + } + } + } }