2 * Copyright (c) 2013 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 org.opendaylight.controller.config.api.ModuleIdentifier;
11 import org.opendaylight.controller.config.api.annotations.ServiceInterfaceAnnotation;
12 import org.osgi.framework.BundleContext;
13 import org.osgi.framework.ServiceRegistration;
14 import org.slf4j.Logger;
15 import org.slf4j.LoggerFactory;
17 import javax.annotation.concurrent.GuardedBy;
18 import java.util.Dictionary;
19 import java.util.HashSet;
20 import java.util.Hashtable;
22 import java.util.Map.Entry;
25 import static com.google.common.base.Preconditions.checkState;
28 * Registers instantiated beans as OSGi services and unregisters these services
29 * if beans are destroyed.
31 public class BeanToOsgiServiceManager {
32 private static final String SERVICE_NAME_OSGI_PROP = "name";
35 * To be called for every created, reconfigured and recreated config bean.
36 * It is expected that before using this method OSGi service registry will
37 * be cleaned from previous registrations.
39 public OsgiRegistration registerToOsgi(AutoCloseable instance, ModuleIdentifier moduleIdentifier,
40 BundleContext bundleContext,
41 Map<String, ServiceInterfaceAnnotation> serviceNamesToAnnotations) {
42 return new OsgiRegistration(instance, moduleIdentifier, bundleContext, serviceNamesToAnnotations);
45 private static Dictionary<String, String> createProps(String serviceName) {
46 Hashtable<String, String> result = new Hashtable<>();
47 result.put(SERVICE_NAME_OSGI_PROP, serviceName);
52 public static class OsgiRegistration implements AutoCloseable {
53 private static final Logger logger = LoggerFactory.getLogger(OsgiRegistration.class);
56 private AutoCloseable instance;
57 private final ModuleIdentifier moduleIdentifier;
59 private final Set<ServiceRegistration<?>> serviceRegistrations;
61 private final Map<String, ServiceInterfaceAnnotation> serviceNamesToAnnotations;
63 public OsgiRegistration(AutoCloseable instance, ModuleIdentifier moduleIdentifier,
64 BundleContext bundleContext,
65 Map<String, ServiceInterfaceAnnotation> serviceNamesToAnnotations) {
66 this.instance = instance;
67 this.moduleIdentifier = moduleIdentifier;
68 this.serviceNamesToAnnotations = serviceNamesToAnnotations;
69 this.serviceRegistrations = registerToSR(instance, bundleContext, serviceNamesToAnnotations);
72 private static Set<ServiceRegistration<?>> registerToSR(AutoCloseable instance, BundleContext bundleContext,
73 Map<String, ServiceInterfaceAnnotation> serviceNamesToAnnotations) {
74 Set<ServiceRegistration<?>> serviceRegistrations = new HashSet<>();
75 for (Entry<String, ServiceInterfaceAnnotation> entry : serviceNamesToAnnotations.entrySet()) {
76 Class<?> requiredInterface = entry.getValue().osgiRegistrationType();
77 checkState(requiredInterface.isInstance(instance), instance.getClass().getName() +
78 " instance should implement " + requiredInterface.getName());
79 Dictionary<String, String> propertiesForOsgi = createProps(entry.getKey());
80 ServiceRegistration<?> serviceRegistration = bundleContext
81 .registerService(requiredInterface.getName(), instance, propertiesForOsgi);
82 serviceRegistrations.add(serviceRegistration);
84 return serviceRegistrations;
88 public synchronized void close() {
89 for (ServiceRegistration<?> serviceRegistration : serviceRegistrations) {
90 serviceRegistration.unregister();
92 serviceRegistrations.clear();
95 public synchronized void updateRegistrations(Map<String, ServiceInterfaceAnnotation> newAnnotationMapping,
96 BundleContext bundleContext, AutoCloseable newInstance) {
97 boolean notEquals = this.instance != newInstance;
98 notEquals |= newAnnotationMapping.equals(serviceNamesToAnnotations) == false;
100 // FIXME: changing from old state to new state can be improved by computing the diff
101 logger.debug("Detected change in service registrations for {}: old: {}, new: {}", moduleIdentifier,
102 serviceNamesToAnnotations, newAnnotationMapping);
104 this.instance = newInstance;
105 Set<ServiceRegistration<?>> newRegs = registerToSR(instance, bundleContext, newAnnotationMapping);
106 serviceRegistrations.clear();
107 serviceRegistrations.addAll(newRegs);