41f577844af5ed448a322a9a21f2f410782632cd
[controller.git] / opendaylight / config / config-manager / src / main / java / org / opendaylight / controller / config / manager / impl / osgi / BeanToOsgiServiceManager.java
1 /*
2  * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
3  *
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
7  */
8 package org.opendaylight.controller.config.manager.impl.osgi;
9
10 import org.opendaylight.controller.config.api.ModuleIdentifier;
11 import org.opendaylight.controller.config.api.annotations.ServiceInterfaceAnnotation;
12 import org.opendaylight.controller.config.manager.impl.util.InterfacesHelper;
13 import org.opendaylight.controller.config.spi.Module;
14 import org.osgi.framework.BundleContext;
15 import org.osgi.framework.ServiceRegistration;
16
17 import java.util.Dictionary;
18 import java.util.HashSet;
19 import java.util.Hashtable;
20 import java.util.Set;
21
22 /**
23  * Registers instantiated beans as OSGi services and unregisters these services
24  * if beans are destroyed.
25  */
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";
30
31     /**
32      * To be called for every created, reconfigured and recreated config bean.
33      * It is expected that before using this method OSGi service registry will
34      * be cleaned from previous registrations.
35      */
36     public OsgiRegistration registerToOsgi(
37             Class<? extends Module> configBeanClass, AutoCloseable instance,
38             ModuleIdentifier moduleIdentifier, BundleContext bundleContext) {
39         try {
40             final Set<Class<?>> configuresInterfaces = InterfacesHelper
41                     .getOsgiRegistrationTypes(configBeanClass);
42             checkInstanceImplementing(instance, configuresInterfaces);
43
44             // bundleContext.registerService blows up with empty 'clazzes'
45             if (configuresInterfaces.isEmpty() == false) {
46                 final Dictionary<String, ?> propertiesForOsgi = getPropertiesForOsgi(moduleIdentifier);
47                 final ServiceRegistration<?> serviceRegistration = bundleContext
48                         .registerService(classesToNames(configuresInterfaces), instance, propertiesForOsgi);
49                 return new OsgiRegistration(serviceRegistration);
50             } else {
51                 return new OsgiRegistration();
52             }
53         } catch (IllegalStateException e) {
54             throw new IllegalStateException(
55                     "Error while registering instance into OSGi Service Registry: "
56                             + moduleIdentifier, e);
57         }
58     }
59
60     private static String[] classesToNames(Set<Class<?>> cfgs) {
61         String[] result = new String[cfgs.size()];
62         int i = 0;
63         for (Class<?> cfg : cfgs) {
64             result[i] = cfg.getName();
65             i++;
66         }
67         return result;
68     }
69
70     private void checkInstanceImplementing(AutoCloseable instance,
71             Set<Class<?>> configures) {
72         Set<Class<?>> missing = new HashSet<>();
73         for (Class<?> requiredIfc : configures) {
74             if (requiredIfc.isInstance(instance) == false) {
75                 missing.add(requiredIfc);
76             }
77         }
78         if (missing.isEmpty() == false) {
79             throw new IllegalStateException(
80                     instance.getClass()
81                             + " does not implement following interfaces as announced by "
82                             + ServiceInterfaceAnnotation.class.getName()
83                             + " annotation :" + missing);
84         }
85     }
86
87     private static Dictionary<String, ?> getPropertiesForOsgi(
88             ModuleIdentifier moduleIdentifier) {
89         Hashtable<String, String> table = new Hashtable<>();
90         table.put(IMPLEMENTATION_NAME_OSGI_PROP,
91                 moduleIdentifier.getFactoryName());
92         table.put(INSTANCE_NAME_OSGI_PROP, moduleIdentifier.getInstanceName());
93         return table;
94     }
95
96     public static class OsgiRegistration implements AutoCloseable {
97         private final ServiceRegistration<?> serviceRegistration;
98
99         public OsgiRegistration(ServiceRegistration<?> serviceRegistration) {
100             this.serviceRegistration = serviceRegistration;
101         }
102
103         public OsgiRegistration() {
104             this.serviceRegistration = null;
105         }
106
107         @Override
108         public void close() {
109             if (serviceRegistration != null) {
110                 serviceRegistration.unregister();
111             }
112         }
113     }
114
115 }