2 * Copyright (c) 2013, 2017 Cisco Systems, Inc. and others. All rights reserved.
4 * This program and the accompanying materials are made available under the
5 * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6 * and is available at http://www.eclipse.org/legal/epl-v10.html
8 package org.opendaylight.controller.config.manager.impl.osgi;
10 import com.google.common.base.Preconditions;
11 import java.util.Dictionary;
12 import java.util.HashSet;
13 import java.util.Hashtable;
15 import java.util.Map.Entry;
17 import javax.annotation.concurrent.GuardedBy;
18 import org.opendaylight.controller.config.api.ModuleIdentifier;
19 import org.opendaylight.controller.config.api.annotations.ServiceInterfaceAnnotation;
20 import org.osgi.framework.BundleContext;
21 import org.osgi.framework.ServiceRegistration;
22 import org.slf4j.Logger;
23 import org.slf4j.LoggerFactory;
26 * Registers instantiated beans as OSGi services and unregisters these services
27 * if beans are destroyed.
29 public class BeanToOsgiServiceManager {
30 private static final String SERVICE_NAME_OSGI_PROP = "name";
33 * To be called for every created, reconfigured and recreated config bean. It is
34 * expected that before using this method OSGi service registry will be cleaned
35 * from previous registrations.
37 * @param instance instance
38 * @param moduleIdentifier module identifier
39 * @param bundleContext bundle context
40 * @param serviceNamesToAnnotations service names annotations
41 * @return OSGI registration
43 public OsgiRegistration registerToOsgi(final AutoCloseable instance, final ModuleIdentifier moduleIdentifier,
44 final BundleContext bundleContext,
45 final Map<ServiceInterfaceAnnotation, String> serviceNamesToAnnotations) {
46 return new OsgiRegistration(instance, moduleIdentifier, bundleContext, serviceNamesToAnnotations);
49 public static class OsgiRegistration implements AutoCloseable {
50 private static final Logger LOG = LoggerFactory.getLogger(OsgiRegistration.class);
53 private AutoCloseable instance;
54 private final ModuleIdentifier moduleIdentifier;
56 private final Set<ServiceRegistration<?>> serviceRegistrations;
58 private final Map<ServiceInterfaceAnnotation, String> serviceNamesToAnnotations;
60 public OsgiRegistration(final AutoCloseable instance, final ModuleIdentifier moduleIdentifier,
61 final BundleContext bundleContext,
62 final Map<ServiceInterfaceAnnotation, String /* service ref name */> serviceNamesToAnnotations) {
63 this.instance = instance;
64 this.moduleIdentifier = moduleIdentifier;
65 this.serviceNamesToAnnotations = serviceNamesToAnnotations;
66 this.serviceRegistrations = registerToSR(instance, bundleContext, serviceNamesToAnnotations);
69 private static Set<ServiceRegistration<?>> registerToSR(final AutoCloseable instance,
70 final BundleContext bundleContext,
71 final Map<ServiceInterfaceAnnotation, String /* service ref name */> serviceNamesToAnnotations) {
72 Set<ServiceRegistration<?>> serviceRegistrations = new HashSet<>();
73 for (Entry<ServiceInterfaceAnnotation, String /* service ref name */> entry : serviceNamesToAnnotations
75 ServiceInterfaceAnnotation annotation = entry.getKey();
76 Class<?> requiredInterface = annotation.osgiRegistrationType();
78 if (!annotation.registerToOsgi()) {
79 LOG.debug("registerToOsgi for service interface {} is false - not registering", requiredInterface);
83 Preconditions.checkState(requiredInterface.isInstance(instance),
84 instance.getClass().getName() + " instance should implement " + requiredInterface.getName());
85 Dictionary<String, String> propertiesForOsgi = createProps(entry.getValue());
86 ServiceRegistration<?> serviceRegistration = bundleContext.registerService(requiredInterface.getName(),
87 instance, propertiesForOsgi);
88 serviceRegistrations.add(serviceRegistration);
90 return serviceRegistrations;
94 public synchronized void close() {
95 for (ServiceRegistration<?> serviceRegistration : serviceRegistrations) {
97 serviceRegistration.unregister();
98 } catch (final IllegalStateException e) {
99 LOG.trace("Cannot unregister {}", serviceRegistration, e);
102 serviceRegistrations.clear();
105 public synchronized void updateRegistrations(
106 final Map<ServiceInterfaceAnnotation, String /* service ref name */> newAnnotationMapping,
107 final BundleContext bundleContext, final AutoCloseable newInstance) {
108 boolean notEquals = !this.instance.equals(newInstance);
109 notEquals |= !newAnnotationMapping.equals(serviceNamesToAnnotations);
111 // FIXME: changing from old state to new state can be improved by computing the
113 LOG.debug("Detected change in service registrations for {}: old: {}, new: {}", moduleIdentifier,
114 serviceNamesToAnnotations, newAnnotationMapping);
116 this.instance = newInstance;
117 Set<ServiceRegistration<?>> newRegs = registerToSR(instance, bundleContext, newAnnotationMapping);
118 serviceRegistrations.clear();
119 serviceRegistrations.addAll(newRegs);
123 private static Dictionary<String, String> createProps(final String serviceName) {
124 Hashtable<String, String> result = new Hashtable<>();
125 result.put(SERVICE_NAME_OSGI_PROP, serviceName);