/* * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved. * * This program and the accompanying materials are made available under the * terms of the Eclipse Public License v1.0 which accompanies this distribution, * and is available at http://www.eclipse.org/legal/epl-v10.html */ package org.opendaylight.controller.config.manager.impl.jmx; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import javax.annotation.concurrent.GuardedBy; import javax.management.InstanceAlreadyExistsException; import javax.management.InstanceNotFoundException; import javax.management.JMX; import javax.management.MBeanRegistrationException; import javax.management.MBeanServer; import javax.management.NotCompliantMBeanException; import javax.management.ObjectName; import javax.management.QueryExp; import java.io.Closeable; import java.util.ArrayList; import java.util.Collections; import java.util.HashSet; import java.util.List; import java.util.Set; public class InternalJMXRegistrator implements Closeable { private static final Logger logger = LoggerFactory .getLogger(InternalJMXRegistrator.class); private final MBeanServer configMBeanServer; public InternalJMXRegistrator(MBeanServer configMBeanServer) { this.configMBeanServer = configMBeanServer; } static class InternalJMXRegistration implements AutoCloseable { private final InternalJMXRegistrator internalJMXRegistrator; private final ObjectName on; InternalJMXRegistration(InternalJMXRegistrator internalJMXRegistrator, ObjectName on) { this.internalJMXRegistrator = internalJMXRegistrator; this.on = on; } @Override public void close() { internalJMXRegistrator.unregisterMBean(on); } } @GuardedBy("this") private final Set registeredObjectNames = new HashSet<>(); @GuardedBy("this") private final List children = new ArrayList<>(); public synchronized InternalJMXRegistration registerMBean(Object object, ObjectName on) throws InstanceAlreadyExistsException { try { configMBeanServer.registerMBean(object, on); } catch (MBeanRegistrationException | NotCompliantMBeanException e) { throw new IllegalStateException(e); } registeredObjectNames.add(on); return new InternalJMXRegistration(this, on); } private synchronized void unregisterMBean(ObjectName on) { // first check that on was registered using this instance boolean removed = registeredObjectNames.remove(on); if (!removed) { throw new IllegalStateException("Cannot unregister - ObjectName not found in 'registeredObjectNames': " + on); } try { configMBeanServer.unregisterMBean(on); } catch (InstanceNotFoundException | MBeanRegistrationException e) { throw new IllegalStateException(e); } } public synchronized InternalJMXRegistrator createChild() { InternalJMXRegistrator child = new InternalJMXRegistrator(configMBeanServer); children.add(child); return child; } /** * Allow close to be called multiple times. */ @Override public synchronized void close() { // close children for (InternalJMXRegistrator child : children) { child.close(); } // close registered ONs for (ObjectName on : registeredObjectNames) { try { configMBeanServer.unregisterMBean(on); } catch (Exception e) { logger.warn("Ignoring error while unregistering {}", on, e); } } registeredObjectNames.clear(); } public T newMBeanProxy(ObjectName objectName, Class interfaceClass) { return JMX.newMBeanProxy(configMBeanServer, objectName, interfaceClass); } public T newMBeanProxy(ObjectName objectName, Class interfaceClass, boolean notificationBroadcaster) { return JMX.newMBeanProxy(configMBeanServer, objectName, interfaceClass, notificationBroadcaster); } public T newMXBeanProxy(ObjectName objectName, Class interfaceClass) { return JMX .newMXBeanProxy(configMBeanServer, objectName, interfaceClass); } public T newMXBeanProxy(ObjectName objectName, Class interfaceClass, boolean notificationBroadcaster) { return JMX.newMXBeanProxy(configMBeanServer, objectName, interfaceClass, notificationBroadcaster); } public Set getRegisteredObjectNames() { return Collections.unmodifiableSet(registeredObjectNames); } public Set queryNames(ObjectName name, QueryExp query) { Set result = configMBeanServer.queryNames(name, query); // keep only those that were registered using this instance return getSameNames(result); } private synchronized Set getSameNames(Set superSet) { Set result = new HashSet<>(superSet); result.retainAll(registeredObjectNames); for (InternalJMXRegistrator child : children) { result.addAll(child.getSameNames(superSet)); } return result; } }