Initial code drop of yang model driven configuration system
[controller.git] / opendaylight / config / config-manager / src / main / java / org / opendaylight / controller / config / manager / impl / jmx / InternalJMXRegistrator.java
diff --git a/opendaylight/config/config-manager/src/main/java/org/opendaylight/controller/config/manager/impl/jmx/InternalJMXRegistrator.java b/opendaylight/config/config-manager/src/main/java/org/opendaylight/controller/config/manager/impl/jmx/InternalJMXRegistrator.java
new file mode 100644 (file)
index 0000000..5d77156
--- /dev/null
@@ -0,0 +1,150 @@
+/*
+ * 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 java.io.Closeable;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+import javax.annotation.concurrent.GuardedBy;
+import javax.management.InstanceAlreadyExistsException;
+import javax.management.JMX;
+import javax.management.MBeanServer;
+import javax.management.ObjectName;
+import javax.management.QueryExp;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+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<ObjectName> registeredObjectNames = new HashSet<>();
+    private final List<InternalJMXRegistrator> children = new ArrayList<>();
+
+    public synchronized InternalJMXRegistration registerMBean(Object object,
+            ObjectName on) throws InstanceAlreadyExistsException {
+        try {
+            configMBeanServer.registerMBean(object, on);
+        } catch (InstanceAlreadyExistsException e) {
+            throw e;
+        } catch (Exception e) {
+            throw new RuntimeException(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 (Exception e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+    public 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> T newMBeanProxy(ObjectName objectName, Class<T> interfaceClass) {
+        return JMX.newMBeanProxy(configMBeanServer, objectName, interfaceClass);
+    }
+
+    public <T> T newMBeanProxy(ObjectName objectName, Class<T> interfaceClass,
+            boolean notificationBroadcaster) {
+        return JMX.newMBeanProxy(configMBeanServer, objectName, interfaceClass,
+                notificationBroadcaster);
+    }
+
+    public <T> T newMXBeanProxy(ObjectName objectName, Class<T> interfaceClass) {
+        return JMX
+                .newMXBeanProxy(configMBeanServer, objectName, interfaceClass);
+    }
+
+    public <T> T newMXBeanProxy(ObjectName objectName, Class<T> interfaceClass,
+            boolean notificationBroadcaster) {
+        return JMX.newMXBeanProxy(configMBeanServer, objectName,
+                interfaceClass, notificationBroadcaster);
+    }
+
+    public Set<ObjectName> getRegisteredObjectNames() {
+        return Collections.unmodifiableSet(registeredObjectNames);
+    }
+
+    public Set<ObjectName> queryNames(ObjectName name, QueryExp query) {
+        Set<ObjectName> result = configMBeanServer.queryNames(name, query);
+        // keep only those that were registered using this instance
+        return getSameNames(result);
+    }
+
+    private Set<ObjectName> getSameNames(Set<ObjectName> superSet) {
+        Set<ObjectName> result = new HashSet<>(superSet);
+        result.retainAll(registeredObjectNames);
+        for (InternalJMXRegistrator child : children) {
+            result.addAll(child.getSameNames(superSet));
+        }
+        return result;
+    }
+
+}