Cleanup RpcRoutingStrategy definition
[controller.git] / opendaylight / config / config-manager / src / main / java / org / opendaylight / controller / config / manager / impl / jmx / InternalJMXRegistrator.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.jmx;
9
10 import org.slf4j.Logger;
11 import org.slf4j.LoggerFactory;
12
13 import javax.annotation.concurrent.GuardedBy;
14 import javax.management.InstanceAlreadyExistsException;
15 import javax.management.InstanceNotFoundException;
16 import javax.management.JMX;
17 import javax.management.MBeanRegistrationException;
18 import javax.management.MBeanServer;
19 import javax.management.NotCompliantMBeanException;
20 import javax.management.ObjectName;
21 import javax.management.QueryExp;
22 import java.io.Closeable;
23 import java.util.ArrayList;
24 import java.util.Collections;
25 import java.util.HashSet;
26 import java.util.List;
27 import java.util.Set;
28
29 public class InternalJMXRegistrator implements Closeable {
30     private static final Logger logger = LoggerFactory
31             .getLogger(InternalJMXRegistrator.class);
32     private final MBeanServer configMBeanServer;
33
34     public InternalJMXRegistrator(MBeanServer configMBeanServer) {
35         this.configMBeanServer = configMBeanServer;
36     }
37
38     static class InternalJMXRegistration implements AutoCloseable {
39         private final InternalJMXRegistrator internalJMXRegistrator;
40         private final ObjectName on;
41
42         InternalJMXRegistration(InternalJMXRegistrator internalJMXRegistrator,
43                                 ObjectName on) {
44             this.internalJMXRegistrator = internalJMXRegistrator;
45             this.on = on;
46         }
47
48         @Override
49         public void close() {
50             internalJMXRegistrator.unregisterMBean(on);
51         }
52     }
53
54     @GuardedBy("this")
55     private final Set<ObjectName> registeredObjectNames = new HashSet<>();
56     private final List<InternalJMXRegistrator> children = new ArrayList<>();
57
58     public synchronized InternalJMXRegistration registerMBean(Object object,
59                                                               ObjectName on) throws InstanceAlreadyExistsException {
60         try {
61             configMBeanServer.registerMBean(object, on);
62         } catch (MBeanRegistrationException | NotCompliantMBeanException e) {
63             throw new IllegalStateException(e);
64         }
65         registeredObjectNames.add(on);
66         return new InternalJMXRegistration(this, on);
67     }
68
69     private synchronized void unregisterMBean(ObjectName on) {
70         // first check that on was registered using this instance
71         boolean removed = registeredObjectNames.remove(on);
72         if (!removed) {
73             throw new IllegalStateException("Cannot unregister - ObjectName not found in 'registeredObjectNames': " + on);
74         }
75         try {
76             configMBeanServer.unregisterMBean(on);
77         } catch (InstanceNotFoundException | MBeanRegistrationException e) {
78             throw new IllegalStateException(e);
79         }
80     }
81
82     public InternalJMXRegistrator createChild() {
83         InternalJMXRegistrator child = new InternalJMXRegistrator(
84                 configMBeanServer);
85         children.add(child);
86         return child;
87     }
88
89     /**
90      * Allow close to be called multiple times.
91      */
92     @Override
93     public synchronized void close() {
94         // close children
95         for (InternalJMXRegistrator child : children) {
96             child.close();
97         }
98         // close registered ONs
99         for (ObjectName on : registeredObjectNames) {
100             try {
101                 configMBeanServer.unregisterMBean(on);
102             } catch (Exception e) {
103                 logger.warn("Ignoring error while unregistering {}", on, e);
104             }
105         }
106         registeredObjectNames.clear();
107     }
108
109     public <T> T newMBeanProxy(ObjectName objectName, Class<T> interfaceClass) {
110         return JMX.newMBeanProxy(configMBeanServer, objectName, interfaceClass);
111     }
112
113     public <T> T newMBeanProxy(ObjectName objectName, Class<T> interfaceClass,
114                                boolean notificationBroadcaster) {
115         return JMX.newMBeanProxy(configMBeanServer, objectName, interfaceClass,
116                 notificationBroadcaster);
117     }
118
119     public <T> T newMXBeanProxy(ObjectName objectName, Class<T> interfaceClass) {
120         return JMX
121                 .newMXBeanProxy(configMBeanServer, objectName, interfaceClass);
122     }
123
124     public <T> T newMXBeanProxy(ObjectName objectName, Class<T> interfaceClass,
125                                 boolean notificationBroadcaster) {
126         return JMX.newMXBeanProxy(configMBeanServer, objectName,
127                 interfaceClass, notificationBroadcaster);
128     }
129
130     public Set<ObjectName> getRegisteredObjectNames() {
131         return Collections.unmodifiableSet(registeredObjectNames);
132     }
133
134     public Set<ObjectName> queryNames(ObjectName name, QueryExp query) {
135         Set<ObjectName> result = configMBeanServer.queryNames(name, query);
136         // keep only those that were registered using this instance
137         return getSameNames(result);
138     }
139
140     private Set<ObjectName> getSameNames(Set<ObjectName> superSet) {
141         Set<ObjectName> result = new HashSet<>(superSet);
142         result.retainAll(registeredObjectNames);
143         for (InternalJMXRegistrator child : children) {
144             result.addAll(child.getSameNames(superSet));
145         }
146         return result;
147     }
148
149 }