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