Merge "Add reverse() method in Edge and Path classes"
[controller.git] / opendaylight / config / config-manager / src / main / java / org / opendaylight / controller / config / manager / impl / ServiceReferenceRegistryImpl.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;
9
10 import org.opendaylight.controller.config.api.LookupRegistry;
11 import org.opendaylight.controller.config.api.ModuleIdentifier;
12 import org.opendaylight.controller.config.api.ServiceReferenceReadableRegistry;
13 import org.opendaylight.controller.config.api.ServiceReferenceWritableRegistry;
14 import org.opendaylight.controller.config.api.annotations.ServiceInterfaceAnnotation;
15 import org.opendaylight.controller.config.api.jmx.ObjectNameUtil;
16 import org.opendaylight.controller.config.manager.impl.jmx.BaseJMXRegistrator;
17 import org.opendaylight.controller.config.manager.impl.jmx.ServiceReference;
18 import org.opendaylight.controller.config.manager.impl.jmx.ServiceReferenceMXBeanImpl;
19 import org.opendaylight.controller.config.manager.impl.jmx.ServiceReferenceRegistrator;
20 import org.opendaylight.controller.config.manager.impl.jmx.ServiceReferenceRegistrator.ServiceReferenceJMXRegistration;
21 import org.opendaylight.controller.config.manager.impl.jmx.ServiceReferenceRegistrator.ServiceReferenceTransactionRegistratorFactory;
22 import org.opendaylight.controller.config.manager.impl.jmx.ServiceReferenceRegistrator.ServiceReferenceTransactionRegistratorFactoryImpl;
23 import org.opendaylight.controller.config.manager.impl.util.InterfacesHelper;
24 import org.opendaylight.controller.config.spi.ModuleFactory;
25 import org.osgi.framework.BundleContext;
26 import org.slf4j.Logger;
27 import org.slf4j.LoggerFactory;
28
29 import javax.management.InstanceAlreadyExistsException;
30 import javax.management.InstanceNotFoundException;
31 import javax.management.ObjectName;
32 import java.util.Collections;
33 import java.util.HashMap;
34 import java.util.HashSet;
35 import java.util.Map;
36 import java.util.Map.Entry;
37 import java.util.Set;
38
39 public class ServiceReferenceRegistryImpl implements CloseableServiceReferenceReadableRegistry, ServiceReferenceWritableRegistry {
40     private static final Logger logger = LoggerFactory.getLogger(ServiceReferenceRegistryImpl.class);
41
42     private final Map<String, ModuleFactory> factories;
43     private final Map<String, Set<String>> factoryNamesToQNames;
44     // validator of incoming ObjectNames - throws InstanceNotFoundException if not found either in registry or transaction
45     private final LookupRegistry lookupRegistry;
46     private final ServiceReferenceRegistrator serviceReferenceRegistrator;
47     // helper method for getting QName of SI from namespace + local name
48     private final Map<String /* namespace */, Map<String /* local name */, ServiceInterfaceAnnotation>> namespacesToAnnotations;
49     // all Service Interface qNames for sanity checking
50     private final Set<String /* qName */> allQNames;
51
52     // actual reference database
53     private final Map<ServiceReference, ModuleIdentifier> refNames = new HashMap<>();
54     private final boolean writable;
55     private final Map<ServiceReference, Entry<ServiceReferenceMXBeanImpl, ServiceReferenceJMXRegistration>> mBeans = new HashMap<>();
56
57     /**
58      * Static constructor for config registry. Since only transaction can write to this registry, it will
59      * return blank state.
60      */
61     public static CloseableServiceReferenceReadableRegistry createInitialSRLookupRegistry() {
62         // since this is initial state, just throw exception:
63         LookupRegistry lookupRegistry = new LookupRegistry() {
64             @Override
65             public Set<ObjectName> lookupConfigBeans() {
66                 throw new UnsupportedOperationException();
67             }
68
69             @Override
70             public Set<ObjectName> lookupConfigBeans(String moduleName) {
71                 throw new UnsupportedOperationException();
72             }
73
74             @Override
75             public Set<ObjectName> lookupConfigBeans(String moduleName, String instanceName) {
76                 throw new UnsupportedOperationException();
77             }
78
79             @Override
80             public ObjectName lookupConfigBean(String moduleName, String instanceName) throws InstanceNotFoundException {
81                 throw new UnsupportedOperationException();
82             }
83
84             @Override
85             public void checkConfigBeanExists(ObjectName objectName) throws InstanceNotFoundException {
86                 throw new InstanceNotFoundException("Cannot find " + objectName + " - Tried to use mocking registry");
87             }
88
89             @Override
90             public Set<String> getAvailableModuleFactoryQNames() {
91                 throw new UnsupportedOperationException();
92             }
93
94             @Override
95             public String toString() {
96                 return "initial";
97             }
98         };
99         ServiceReferenceTransactionRegistratorFactory serviceReferenceRegistratorFactory = new ServiceReferenceTransactionRegistratorFactory(){
100             @Override
101             public ServiceReferenceRegistrator create() {
102                 return new ServiceReferenceRegistrator() {
103                     @Override
104                     public String getNullableTransactionName() {
105                         throw new UnsupportedOperationException();
106                     }
107
108                     @Override
109                     public ServiceReferenceJMXRegistration registerMBean(ServiceReferenceMXBeanImpl object, ObjectName on) throws InstanceAlreadyExistsException {
110                         throw new UnsupportedOperationException();
111                     }
112
113                     @Override
114                     public void close() {
115
116                     }
117                 };
118             }
119         };
120         return new ServiceReferenceRegistryImpl(Collections.<String, ModuleFactory>emptyMap(), lookupRegistry,
121                 serviceReferenceRegistratorFactory, false);
122     }
123
124     /**
125      * Static constructor for transaction controller. Take current state as seen by config registry, allow writing new data.
126      */
127     public static ServiceReferenceWritableRegistry createSRWritableRegistry(ServiceReferenceReadableRegistry oldReadableRegistry,
128                                                     ConfigTransactionLookupRegistry txLookupRegistry,
129                                                     Map<String, Map.Entry<ModuleFactory, BundleContext>> currentlyRegisteredFactories) {
130
131         if (txLookupRegistry == null) {
132             throw new IllegalArgumentException("txLookupRegistry is null");
133         }
134         ServiceReferenceRegistryImpl old = (ServiceReferenceRegistryImpl) oldReadableRegistry;
135         Map<String, ModuleFactory> factories = extractFactoriesMap(currentlyRegisteredFactories);
136         ServiceReferenceTransactionRegistratorFactory serviceReferenceRegistratorFactory = new ServiceReferenceTransactionRegistratorFactoryImpl(
137                 txLookupRegistry.getTxModuleJMXRegistrator(), txLookupRegistry.getTxModuleJMXRegistrator().getTransactionName());
138         ServiceReferenceRegistryImpl newRegistry = new ServiceReferenceRegistryImpl(factories, txLookupRegistry,
139                 serviceReferenceRegistratorFactory, true);
140         copy(old, newRegistry, txLookupRegistry.getTransactionIdentifier().getName());
141         return newRegistry;
142     }
143
144     /**
145      * Copy back state to config registry after commit.
146      */
147     public static CloseableServiceReferenceReadableRegistry createSRReadableRegistry(ServiceReferenceWritableRegistry oldWritableRegistry,
148                                                                             LookupRegistry lookupRegistry, BaseJMXRegistrator baseJMXRegistrator) {
149         ServiceReferenceRegistryImpl old = (ServiceReferenceRegistryImpl) oldWritableRegistry;
150
151         // even if factories do change, nothing in the mapping can change between transactions
152         ServiceReferenceTransactionRegistratorFactory serviceReferenceRegistratorFactory = new ServiceReferenceTransactionRegistratorFactoryImpl(baseJMXRegistrator);
153         ServiceReferenceRegistryImpl newRegistry = new ServiceReferenceRegistryImpl(old.factories, lookupRegistry,
154                 serviceReferenceRegistratorFactory, false);
155         copy(old, newRegistry, null);
156         return newRegistry;
157     }
158
159     /**
160      * Fill refNames and mBeans maps from old instance
161      */
162     private static void copy(ServiceReferenceRegistryImpl old, ServiceReferenceRegistryImpl newRegistry, String nullableDstTransactionName) {
163         for (Entry<ServiceReference, Entry<ServiceReferenceMXBeanImpl, ServiceReferenceJMXRegistration>> refNameEntry : old.mBeans.entrySet()) {
164             ObjectName currentImplementation;
165             ObjectName currentImplementationSrc = refNameEntry.getValue().getKey().getCurrentImplementation();
166             if (nullableDstTransactionName != null) {
167                 currentImplementation = ObjectNameUtil.withTransactionName(currentImplementationSrc, nullableDstTransactionName);
168             } else {
169                 currentImplementation = ObjectNameUtil.withoutTransactionName(currentImplementationSrc);
170             }
171             try {
172                 boolean skipChecks = true;
173                 newRegistry.saveServiceReference(refNameEntry.getKey(), currentImplementation, skipChecks);
174             } catch (InstanceNotFoundException e) {
175                 logger.error("Cannot save service reference({}, {})", refNameEntry.getKey(), currentImplementation);
176                 throw new IllegalStateException("Possible code error", e);
177             }
178         }
179     }
180
181     private static Map<String, ModuleFactory> extractFactoriesMap(Map<String, Map.Entry<ModuleFactory, BundleContext>> currentlyRegisteredFactories) {
182         Map<String, ModuleFactory> result = new HashMap<>();
183         for (Entry<String, Entry<ModuleFactory, BundleContext>> entry : currentlyRegisteredFactories.entrySet()) {
184             result.put(entry.getKey(), entry.getValue().getKey());
185         }
186         return result;
187     }
188
189     private ServiceReferenceRegistryImpl(Map<String, ModuleFactory> factories, LookupRegistry lookupRegistry,
190                                          ServiceReferenceTransactionRegistratorFactory serviceReferenceRegistratorFactory,
191                                          boolean writable) {
192         this.factories = factories;
193         this.writable = writable;
194         this.lookupRegistry = lookupRegistry;
195
196         this.serviceReferenceRegistrator = serviceReferenceRegistratorFactory.create();
197
198         Map<String, Set<String /* QName */>> modifiableFactoryNamesToQNames = new HashMap<>();
199         Set<ServiceInterfaceAnnotation> allAnnotations = new HashSet<>();
200         Set<String /* qName */> allQNames = new HashSet<>();
201         for (Entry<String, ModuleFactory> entry : factories.entrySet()) {
202             if (entry.getKey().equals(entry.getValue().getImplementationName()) == false) {
203                 logger.error("Possible error in code: Mismatch between supplied and actual name of {}", entry);
204                 throw new IllegalArgumentException("Possible error in code: Mismatch between supplied and actual name of " + entry);
205             }
206             Set<ServiceInterfaceAnnotation> siAnnotations = InterfacesHelper.getServiceInterfaceAnnotations(entry.getValue());
207             Set<String> qNames = new HashSet<>();
208             for (ServiceInterfaceAnnotation sia: siAnnotations) {
209                 qNames.add(sia.value());
210             }
211             allAnnotations.addAll(siAnnotations);
212             allQNames.addAll(qNames);
213             modifiableFactoryNamesToQNames.put(entry.getKey(), Collections.unmodifiableSet(qNames));
214         }
215         this.factoryNamesToQNames = Collections.unmodifiableMap(modifiableFactoryNamesToQNames);
216         this.allQNames = Collections.unmodifiableSet(allQNames);
217         // fill namespacesToAnnotations
218         Map<String /* namespace */, Map<String /* localName */, ServiceInterfaceAnnotation>> modifiableNamespacesToAnnotations =
219                 new HashMap<>();
220         for (ServiceInterfaceAnnotation sia : allAnnotations) {
221             Map<String, ServiceInterfaceAnnotation> ofNamespace = modifiableNamespacesToAnnotations.get(sia.namespace());
222             if (ofNamespace == null) {
223                 ofNamespace = new HashMap<>();
224                 modifiableNamespacesToAnnotations.put(sia.namespace(), ofNamespace);
225             }
226             if (ofNamespace.containsKey(sia.localName())) {
227                 logger.error("Cannot construct namespacesToAnnotations map, conflict between local names in {}, offending local name: {}, map so far {}",
228                         sia.namespace(), sia.localName(), modifiableNamespacesToAnnotations);
229                 throw new IllegalArgumentException("Conflict between local names in " + sia.namespace() + " : " + sia.localName());
230             }
231             ofNamespace.put(sia.localName(), sia);
232         }
233         this.namespacesToAnnotations = Collections.unmodifiableMap(modifiableNamespacesToAnnotations);
234         // copy refNames
235         logger.trace("factoryNamesToQNames:{}", this.factoryNamesToQNames);
236     }
237
238
239     @Override
240     public synchronized Set<String> lookupServiceInterfaceNames(ObjectName objectName) throws InstanceNotFoundException {
241         lookupRegistry.checkConfigBeanExists(objectName);
242
243         String factoryName = ObjectNameUtil.getFactoryName(objectName);
244         Set<String> serviceInterfaceAnnotations = factoryNamesToQNames.get(factoryName);
245         if (serviceInterfaceAnnotations == null) {
246             logger.error("Possible error in code: cannot find factory annotations of '{}' extracted from ON {} in {}",
247                     factoryName, objectName, factoryNamesToQNames);
248             throw new IllegalArgumentException("Cannot find factory with name " + factoryName);
249         }
250         return serviceInterfaceAnnotations;
251     }
252
253     @Override
254     public synchronized String getServiceInterfaceName(String namespace, String localName) {
255         Map<String /* localName */, ServiceInterfaceAnnotation> ofNamespace = namespacesToAnnotations.get(namespace);
256         if (ofNamespace == null) {
257             logger.error("Cannot find namespace {} in {}", namespace, namespacesToAnnotations);
258             throw new IllegalArgumentException("Cannot find namespace " + namespace);
259         }
260         ServiceInterfaceAnnotation sia = ofNamespace.get(localName);
261         if (sia == null) {
262             logger.error("Cannot find local name {} in namespace {}, found only {}", localName, namespace, ofNamespace);
263             throw new IllegalArgumentException("Cannot find local name " + localName + " in namespace " + namespace);
264         }
265         return sia.value();
266     }
267
268     // reading:
269
270     @Override
271     public synchronized Map<String /* serviceInterfaceName */, Map<String/* refName */, ObjectName>> getServiceMapping() {
272         Map<String /* serviceInterfaceName */, Map<String/* refName */, ObjectName>> result = new HashMap<>();
273         for (Entry<ServiceReference, ModuleIdentifier> entry: refNames.entrySet()) {
274             String qName = entry.getKey().getServiceInterfaceName();
275             Map<String /* refName */, ObjectName> innerMap = result.get(qName);
276             if (innerMap == null) {
277                 innerMap = new HashMap<>();
278                 result.put(qName, innerMap);
279             }
280             innerMap.put(entry.getKey().getRefName(), getObjectName(entry.getValue()));
281         }
282         return result;
283     }
284
285     private ObjectName getObjectName(ModuleIdentifier moduleIdentifier) {
286         ObjectName on;
287         try {
288             on = lookupRegistry.lookupConfigBean(moduleIdentifier.getFactoryName(), moduleIdentifier.getInstanceName());
289         } catch (InstanceNotFoundException e) {
290             logger.error("Cannot find instance {}", moduleIdentifier);
291             throw new IllegalStateException("Cannot find instance " + moduleIdentifier, e);
292         }
293         return on;
294     }
295
296     @Override
297     public synchronized ObjectName lookupConfigBeanByServiceInterfaceName(String serviceInterfaceQName, String refName) {
298         ServiceReference serviceReference = new ServiceReference(serviceInterfaceQName, refName);
299         ModuleIdentifier moduleIdentifier = refNames.get(serviceReference);
300         if (moduleIdentifier == null) {
301             logger.error("Cannot find qname {} and refName {} in {}", serviceInterfaceQName, refName, refName);
302             throw new IllegalArgumentException("Cannot find " + serviceReference);
303         }
304         return getObjectName(moduleIdentifier);
305     }
306
307     @Override
308     public synchronized Map<String /* refName */, ObjectName> lookupServiceReferencesByServiceInterfaceName(String serviceInterfaceQName) {
309         Map<String, Map<String, ObjectName>> serviceMapping = getServiceMapping();
310         Map<String, ObjectName> innerMap = serviceMapping.get(serviceInterfaceQName);
311         if (innerMap == null) {
312             logger.error("Cannot find qname {} in {}", serviceInterfaceQName, refNames);
313             throw new IllegalArgumentException("Cannot find " + serviceInterfaceQName);
314         }
315         return innerMap;
316     }
317
318     @Override
319     public synchronized ObjectName getServiceReference(String serviceInterfaceQName, String refName) throws InstanceNotFoundException {
320         ServiceReference serviceReference = new ServiceReference(serviceInterfaceQName, refName);
321         if (mBeans.containsKey(serviceReference) == false) {
322             throw new InstanceNotFoundException("Cannot find " + serviceReference);
323         }
324         return getServiceON(serviceReference);
325     }
326
327     @Override
328     public synchronized void checkServiceReferenceExists(ObjectName objectName) throws InstanceNotFoundException {
329         String actualTransactionName = ObjectNameUtil.getTransactionName(objectName);
330         String expectedTransactionName = serviceReferenceRegistrator.getNullableTransactionName();
331         if (writable & actualTransactionName == null || (writable && actualTransactionName.equals(expectedTransactionName) == false)) {
332             throw new IllegalArgumentException("Mismatched transaction name in " + objectName);
333         }
334         String serviceQName = ObjectNameUtil.getServiceQName(objectName);
335         String referenceName = ObjectNameUtil.getReferenceName(objectName);
336         ServiceReference serviceReference = new ServiceReference(serviceQName, referenceName);
337         if (refNames.containsKey(serviceReference) == false) {
338             logger.warn("Cannot find {} in {}", serviceReference, refNames);
339             throw new InstanceNotFoundException("Service reference not found:" + objectName);
340         }
341     }
342
343     // writing:
344
345     private void assertWritable() {
346         if (writable == false) {
347             throw new IllegalStateException("Cannot write to readable registry");
348         }
349     }
350
351     @Override
352     public synchronized ObjectName saveServiceReference(String serviceInterfaceName, String refName, ObjectName moduleON)  throws InstanceNotFoundException {
353         assertWritable();
354         ServiceReference serviceReference = new ServiceReference(serviceInterfaceName, refName);
355         return saveServiceReference(serviceReference, moduleON);
356     }
357
358     private synchronized ObjectName saveServiceReference(ServiceReference serviceReference, ObjectName moduleON)
359             throws InstanceNotFoundException{
360         return saveServiceReference(serviceReference, moduleON, false);
361     }
362
363     private synchronized ObjectName saveServiceReference(ServiceReference serviceReference, ObjectName moduleON,
364                                                          boolean skipChecks) throws InstanceNotFoundException {
365
366         // make sure it is found
367         if (skipChecks == false) {
368             lookupRegistry.checkConfigBeanExists(moduleON);
369         }
370         String factoryName = ObjectNameUtil.getFactoryName(moduleON);
371         String instanceName = ObjectNameUtil.getInstanceName(moduleON);
372         ModuleIdentifier moduleIdentifier = new ModuleIdentifier(factoryName, instanceName);
373
374         // check that service interface name exist
375         Set<String> serviceInterfaceQNames = factoryNamesToQNames.get(moduleIdentifier.getFactoryName());
376         if (serviceInterfaceQNames == null) {
377             logger.error("Possible error in code: cannot find factoryName {} in {}, {}", moduleIdentifier.getFactoryName(),
378                     factoryNamesToQNames, moduleIdentifier);
379             throw new IllegalStateException("Possible error in code: cannot find annotations of existing factory " + moduleIdentifier.getFactoryName());
380         }
381         // supplied serviceInterfaceName must exist in this collection
382         if (serviceInterfaceQNames.contains(serviceReference.getServiceInterfaceName()) == false) {
383             logger.error("Cannot find qName {} with factory name {}, found {}", serviceReference.getServiceInterfaceName(), moduleIdentifier.getFactoryName(), serviceInterfaceQNames);
384             throw new IllegalArgumentException("Cannot find service interface " + serviceReference.getServiceInterfaceName() + " within factory " + moduleIdentifier.getFactoryName());
385         }
386
387
388         // create service reference object name, put to mBeans
389         ObjectName result = getServiceON(serviceReference);
390         Entry<ServiceReferenceMXBeanImpl, ServiceReferenceJMXRegistration> mxBeanEntry = mBeans.get(serviceReference);
391         if (mxBeanEntry == null) {
392             // create dummy mx bean
393             ServiceReferenceMXBeanImpl dummyMXBean = new ServiceReferenceMXBeanImpl(moduleON);
394             ServiceReferenceJMXRegistration dummyMXBeanRegistration;
395             try {
396                 dummyMXBeanRegistration = serviceReferenceRegistrator.registerMBean(dummyMXBean, result);
397             } catch (InstanceAlreadyExistsException e) {
398                 throw new IllegalStateException("Possible error in code. Cannot register " + result, e);
399             }
400             mBeans.put(serviceReference, createMXBeanEntry(dummyMXBean, dummyMXBeanRegistration));
401         } else {
402             // update
403             mxBeanEntry.getKey().setCurrentImplementation(moduleON);
404         }
405         // save to refNames
406         refNames.put(serviceReference, moduleIdentifier);
407         return result;
408     }
409
410     private Entry<ServiceReferenceMXBeanImpl, ServiceReferenceJMXRegistration> createMXBeanEntry(
411             final ServiceReferenceMXBeanImpl mxBean, final ServiceReferenceJMXRegistration registration) {
412         return new Entry<ServiceReferenceMXBeanImpl, ServiceReferenceJMXRegistration>() {
413             @Override
414             public ServiceReferenceMXBeanImpl getKey() {
415                 return mxBean;
416             }
417
418             @Override
419             public ServiceReferenceJMXRegistration getValue() {
420                 return registration;
421             }
422
423             @Override
424             public ServiceReferenceJMXRegistration setValue(ServiceReferenceJMXRegistration value) {
425                 throw new UnsupportedOperationException();
426             }
427         };
428     }
429
430     private ObjectName getServiceON(ServiceReference serviceReference) {
431         if (writable) {
432             return ObjectNameUtil.createTransactionServiceON(serviceReferenceRegistrator.getNullableTransactionName(),
433                     serviceReference.getServiceInterfaceName(), serviceReference.getRefName());
434         } else {
435             return ObjectNameUtil.createReadOnlyServiceON(serviceReference.getServiceInterfaceName(), serviceReference.getRefName());
436         }
437     }
438
439     @Override
440     public synchronized void removeServiceReference(String serviceInterfaceName, String refName) throws InstanceNotFoundException{
441         ServiceReference serviceReference = new ServiceReference(serviceInterfaceName, refName);
442         removeServiceReference(serviceReference);
443     }
444
445     private synchronized void removeServiceReference(ServiceReference serviceReference) throws InstanceNotFoundException {
446         logger.debug("Removing service reference {} from {}", serviceReference, this);
447         assertWritable();
448         // is the qName known?
449         if (allQNames.contains(serviceReference.getServiceInterfaceName()) == false) {
450             logger.error("Cannot find qname {} in {}", serviceReference.getServiceInterfaceName(), allQNames);
451             throw new IllegalArgumentException("Cannot find service interface " + serviceReference.getServiceInterfaceName());
452         }
453         ModuleIdentifier removed = refNames.remove(serviceReference);
454         if (removed == null){
455             throw new InstanceNotFoundException("Cannot find " + serviceReference.getServiceInterfaceName());
456         }
457         Entry<ServiceReferenceMXBeanImpl, ServiceReferenceJMXRegistration> entry = mBeans.remove(serviceReference);
458         if (entry == null) {
459             throw new IllegalStateException("Possible code error: cannot remove from mBeans: " + serviceReference);
460         }
461         entry.getValue().close();
462     }
463
464     @Override
465     public synchronized void removeAllServiceReferences() {
466         assertWritable();
467         for (ServiceReference serviceReference: mBeans.keySet()) {
468             try {
469                 removeServiceReference(serviceReference);
470             } catch (InstanceNotFoundException e) {
471                 throw new IllegalStateException("Possible error in code", e);
472             }
473         }
474     }
475
476     @Override
477     public synchronized boolean removeServiceReferences(ObjectName moduleObjectName) throws InstanceNotFoundException {
478         assertWritable();
479         Set<ServiceReference> serviceReferencesLinkingTo = findServiceReferencesLinkingTo(moduleObjectName);
480         for (ServiceReference sr : serviceReferencesLinkingTo) {
481             removeServiceReference(sr);
482         }
483         return serviceReferencesLinkingTo.isEmpty() == false;
484     }
485
486     private synchronized Set<ServiceReference> findServiceReferencesLinkingTo(ObjectName moduleObjectName)  throws InstanceNotFoundException {
487         lookupRegistry.checkConfigBeanExists(moduleObjectName);
488         String factoryName = ObjectNameUtil.getFactoryName(moduleObjectName);
489         // check that service interface name exist
490         Set<String> serviceInterfaceQNames = factoryNamesToQNames.get(factoryName);
491         if (serviceInterfaceQNames == null) {
492             logger.error("Possible error in code: cannot find factoryName {} in {}, object name {}", factoryName, factoryNamesToQNames, moduleObjectName);
493             throw new IllegalStateException("Possible error in code: cannot find annotations of existing factory " + factoryName);
494         }
495         String instanceName = ObjectNameUtil.getInstanceName(moduleObjectName);
496         ModuleIdentifier moduleIdentifier = new ModuleIdentifier(factoryName, instanceName);
497         Set<ServiceReference> result = new HashSet<>();
498         for (Entry<ServiceReference, ModuleIdentifier> entry : refNames.entrySet()) {
499             if (entry.getValue().equals(moduleIdentifier)) {
500                 result.add(entry.getKey());
501             }
502         }
503         return result;
504     }
505
506
507     @Override
508     public String toString() {
509         return "ServiceReferenceRegistryImpl{" +
510                 "lookupRegistry=" + lookupRegistry +
511                 "refNames=" + refNames +
512                 ", factoryNamesToQNames=" + factoryNamesToQNames +
513                 '}';
514     }
515
516     @Override
517     public void close() {
518         serviceReferenceRegistrator.close();
519     }
520 }