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 java.util.Dictionary;
11 import java.util.HashSet;
12 import java.util.Hashtable;
15 import org.opendaylight.controller.config.api.ModuleIdentifier;
16 import org.opendaylight.controller.config.api.annotations.ServiceInterfaceAnnotation;
17 import org.opendaylight.controller.config.manager.impl.util.InterfacesHelper;
18 import org.opendaylight.controller.config.spi.Module;
19 import org.osgi.framework.BundleContext;
20 import org.osgi.framework.ServiceRegistration;
23 * Registers instantiated beans as OSGi services and unregisters these services
24 * if beans are destroyed.
26 public class BeanToOsgiServiceManager {
27 // name of properties submitted to osgi
28 static final String INSTANCE_NAME_OSGI_PROP = "instanceName";
29 static final String IMPLEMENTATION_NAME_OSGI_PROP = "implementationName";
31 private final BundleContext bundleContext;
33 public BeanToOsgiServiceManager(BundleContext context) {
34 this.bundleContext = context;
38 * To be called for every created, reconfigured and recreated config bean.
39 * It is expected that before using this method OSGi service registry will
40 * be cleaned from previous registrations.
42 public OsgiRegistration registerToOsgi(
43 Class<? extends Module> configBeanClass, AutoCloseable instance,
44 ModuleIdentifier moduleIdentifier) {
46 final Set<Class<?>> configuresInterfaces = InterfacesHelper
47 .getOsgiRegistrationTypes(configBeanClass);
48 checkInstanceImplementing(instance, configuresInterfaces);
50 // bundleContext.registerService blows up with empty 'clazzes'
51 if (configuresInterfaces.isEmpty() == false) {
52 final Dictionary<String, ?> propertiesForOsgi = getPropertiesForOsgi(moduleIdentifier);
53 final ServiceRegistration<?> serviceRegistration = bundleContext
54 .registerService(classesToNames(configuresInterfaces), instance, propertiesForOsgi);
55 return new OsgiRegistration(serviceRegistration);
57 return new OsgiRegistration();
59 } catch (IllegalStateException e) {
60 throw new IllegalStateException(
61 "Error while registering instance into OSGi Service Registry: "
62 + moduleIdentifier, e);
66 private static String[] classesToNames(Set<Class<?>> cfgs) {
67 String[] result = new String[cfgs.size()];
69 for (Class<?> cfg : cfgs) {
70 result[i] = cfg.getName();
76 private void checkInstanceImplementing(AutoCloseable instance,
77 Set<Class<?>> configures) {
78 Set<Class<?>> missing = new HashSet<>();
79 for (Class<?> requiredIfc : configures) {
80 if (requiredIfc.isInstance(instance) == false) {
81 missing.add(requiredIfc);
84 if (missing.isEmpty() == false) {
85 throw new IllegalStateException(
87 + " does not implement following interfaces as announced by "
88 + ServiceInterfaceAnnotation.class.getName()
89 + " annotation :" + missing);
93 private static Dictionary<String, ?> getPropertiesForOsgi(
94 ModuleIdentifier moduleIdentifier) {
95 Hashtable<String, String> table = new Hashtable<>();
96 table.put(IMPLEMENTATION_NAME_OSGI_PROP,
97 moduleIdentifier.getFactoryName());
98 table.put(INSTANCE_NAME_OSGI_PROP, moduleIdentifier.getInstanceName());
102 public static class OsgiRegistration implements AutoCloseable {
103 private final ServiceRegistration<?> serviceRegistration;
105 public OsgiRegistration(ServiceRegistration<?> serviceRegistration) {
106 this.serviceRegistration = serviceRegistration;
109 public OsgiRegistration() {
110 this.serviceRegistration = null;
114 public void close() {
115 if (serviceRegistration != null) {
116 serviceRegistration.unregister();