2 * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved.
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
8 package org.opendaylight.controller.config.manager.impl.jmx;
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;
16 import javax.annotation.concurrent.GuardedBy;
17 import javax.management.InstanceAlreadyExistsException;
18 import javax.management.InstanceNotFoundException;
19 import javax.management.JMX;
20 import javax.management.MBeanRegistrationException;
21 import javax.management.MBeanServer;
22 import javax.management.NotCompliantMBeanException;
23 import javax.management.ObjectName;
24 import javax.management.QueryExp;
25 import org.slf4j.Logger;
26 import org.slf4j.LoggerFactory;
28 public class InternalJMXRegistrator implements Closeable {
29 private static final Logger LOG = LoggerFactory
30 .getLogger(InternalJMXRegistrator.class);
31 private final MBeanServer configMBeanServer;
33 public InternalJMXRegistrator(MBeanServer configMBeanServer) {
34 this.configMBeanServer = configMBeanServer;
37 static class InternalJMXRegistration implements AutoCloseable {
38 private final InternalJMXRegistrator internalJMXRegistrator;
39 private final ObjectName on;
41 InternalJMXRegistration(InternalJMXRegistrator internalJMXRegistrator,
43 this.internalJMXRegistrator = internalJMXRegistrator;
49 internalJMXRegistrator.unregisterMBean(on);
54 private final Set<ObjectName> registeredObjectNames = new HashSet<>();
56 private final List<InternalJMXRegistrator> children = new ArrayList<>();
58 public synchronized InternalJMXRegistration registerMBean(Object object,
59 ObjectName on) throws InstanceAlreadyExistsException {
61 configMBeanServer.registerMBean(object, on);
62 } catch (MBeanRegistrationException | NotCompliantMBeanException e) {
63 throw new IllegalStateException(e);
65 registeredObjectNames.add(on);
66 return new InternalJMXRegistration(this, on);
69 private synchronized void unregisterMBean(ObjectName on) {
70 // first check that on was registered using this instance
71 boolean removed = registeredObjectNames.remove(on);
73 throw new IllegalStateException("Cannot unregister - ObjectName not found in 'registeredObjectNames': " + on);
76 configMBeanServer.unregisterMBean(on);
77 } catch (InstanceNotFoundException | MBeanRegistrationException e) {
78 throw new IllegalStateException(e);
82 public synchronized InternalJMXRegistrator createChild() {
83 InternalJMXRegistrator child = new InternalJMXRegistrator(configMBeanServer);
89 * Allow close to be called multiple times.
92 public synchronized void close() {
94 for (InternalJMXRegistrator child : children) {
97 // close registered ONs
98 for (ObjectName on : registeredObjectNames) {
100 configMBeanServer.unregisterMBean(on);
101 } catch (Exception e) {
102 LOG.warn("Ignoring error while unregistering {}", on, e);
105 registeredObjectNames.clear();
108 public <T> T newMBeanProxy(ObjectName objectName, Class<T> interfaceClass) {
109 return JMX.newMBeanProxy(configMBeanServer, objectName, interfaceClass);
112 public <T> T newMBeanProxy(ObjectName objectName, Class<T> interfaceClass,
113 boolean notificationBroadcaster) {
114 return JMX.newMBeanProxy(configMBeanServer, objectName, interfaceClass,
115 notificationBroadcaster);
118 public <T> T newMXBeanProxy(ObjectName objectName, Class<T> interfaceClass) {
120 .newMXBeanProxy(configMBeanServer, objectName, interfaceClass);
123 public <T> T newMXBeanProxy(ObjectName objectName, Class<T> interfaceClass,
124 boolean notificationBroadcaster) {
125 return JMX.newMXBeanProxy(configMBeanServer, objectName,
126 interfaceClass, notificationBroadcaster);
129 public Set<ObjectName> getRegisteredObjectNames() {
130 return Collections.unmodifiableSet(registeredObjectNames);
133 public Set<ObjectName> queryNames(ObjectName name, QueryExp query) {
134 Set<ObjectName> result = configMBeanServer.queryNames(name, query);
135 // keep only those that were registered using this instance
136 return getSameNames(result);
139 private synchronized Set<ObjectName> getSameNames(Set<ObjectName> superSet) {
140 Set<ObjectName> result = new HashSet<>(superSet);
141 result.retainAll(registeredObjectNames);
142 for (InternalJMXRegistrator child : children) {
143 result.addAll(child.getSameNames(superSet));