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