diff --git a/src/main/java/com/scylladb/jmx/utils/APIBuilder.java b/src/main/java/com/scylladb/jmx/utils/APIBuilder.java
index 941a2bc..b7fb775 100644
--- a/src/main/java/com/scylladb/jmx/utils/APIBuilder.java
+++ b/src/main/java/com/scylladb/jmx/utils/APIBuilder.java
@@ -3,6 +3,8 @@ package com.scylladb.jmx.utils;
* Copyright 2016 ScyllaDB
*/
+import static com.scylladb.jmx.main.Main.client;
+
/*
* This file is part of Scylla.
*
@@ -21,21 +23,13 @@ package com.scylladb.jmx.utils;
*/
import javax.management.MBeanServer;
+import javax.management.MBeanServerBuilder;
import javax.management.MBeanServerDelegate;
-import mx4j.server.ChainedMBeanServerBuilder;
-
-public class APIBuilder extends ChainedMBeanServerBuilder {
- public APIBuilder() {
- super(new mx4j.server.MX4JMBeanServerBuilder());
- }
-
- public MBeanServer newMBeanServer(String defaultDomain, MBeanServer outer,
- MBeanServerDelegate delegate) {
- APIMBeanServer extern = new APIMBeanServer();
- MBeanServer nested = getMBeanServerBuilder().newMBeanServer(
- defaultDomain, outer == null ? extern : outer, delegate);
- extern.setMBeanServer(nested);
- return extern;
+public class APIBuilder extends MBeanServerBuilder {
+ @Override
+ public MBeanServer newMBeanServer(String defaultDomain, MBeanServer outer, MBeanServerDelegate delegate) {
+ MBeanServer nested = super.newMBeanServer(defaultDomain, outer, delegate);
+ return new APIMBeanServer(client, nested);
}
}
\ No newline at end of file
diff --git a/src/main/java/com/scylladb/jmx/utils/APIMBeanServer.java b/src/main/java/com/scylladb/jmx/utils/APIMBeanServer.java
index e3ef0a7..6f2f8f4 100644
--- a/src/main/java/com/scylladb/jmx/utils/APIMBeanServer.java
+++ b/src/main/java/com/scylladb/jmx/utils/APIMBeanServer.java
@@ -1,132 +1,290 @@
package com.scylladb.jmx.utils;
-/**
- * Copyright 2016 ScyllaDB
- */
-/*
-* This file is part of Scylla.
-*
-* Scylla is free software: you can redistribute it and/or modify
-* it under the terms of the GNU Affero General Public License as published by
-* the Free Software Foundation, either version 3 of the License, or
-* (at your option) any later version.
-*
-* Scylla is distributed in the hope that it will be useful,
-* but WITHOUT ANY WARRANTY; without even the implied warranty of
-* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-* GNU General Public License for more details.
-*
-* You should have received a copy of the GNU General Public License
-* along with Scylla. If not, see .
-*/
-import java.lang.reflect.Field;
-import java.lang.reflect.InvocationTargetException;
-import java.lang.reflect.Method;
-import java.util.HashSet;
-import java.util.Hashtable;
-import java.util.Iterator;
-import java.util.Map;
+import java.io.ObjectInputStream;
+import java.net.UnknownHostException;
import java.util.Set;
+import java.util.logging.Logger;
+import java.util.regex.Pattern;
+import javax.management.Attribute;
+import javax.management.AttributeList;
+import javax.management.AttributeNotFoundException;
+import javax.management.InstanceAlreadyExistsException;
+import javax.management.InstanceNotFoundException;
+import javax.management.IntrospectionException;
+import javax.management.InvalidAttributeValueException;
+import javax.management.ListenerNotFoundException;
+import javax.management.MBeanException;
+import javax.management.MBeanInfo;
+import javax.management.MBeanRegistrationException;
import javax.management.MBeanServer;
+import javax.management.MalformedObjectNameException;
+import javax.management.NotCompliantMBeanException;
+import javax.management.NotificationFilter;
+import javax.management.NotificationListener;
+import javax.management.ObjectInstance;
import javax.management.ObjectName;
+import javax.management.OperationsException;
import javax.management.QueryExp;
+import javax.management.ReflectionException;
+import javax.management.loading.ClassLoaderRepository;
+
import org.apache.cassandra.db.ColumnFamilyStore;
import org.apache.cassandra.metrics.StreamingMetrics;
-import mx4j.server.ChainedMBeanServer;
-import mx4j.server.MX4JMBeanServer;
-import mx4j.util.Utils;
+import com.scylladb.jmx.api.APIClient;
-public class APIMBeanServer extends ChainedMBeanServer {
- private static final java.util.logging.Logger logger = java.util.logging.Logger
- .getLogger(APIMBeanServer.class.getName());
+public class APIMBeanServer implements MBeanServer {
+ @SuppressWarnings("unused")
+ private static final Logger logger = Logger.getLogger(APIMBeanServer.class.getName());
- public static void log(String str) {
- logger.finest(str);
+ private final APIClient client;
+ private final MBeanServer server;
+
+ public APIMBeanServer(APIClient client, MBeanServer server) {
+ this.client = client;
+ this.server = server;
}
- public void setMBeanServer(MBeanServer server) {
- if (server != null) {
- try {
- Field f = server.getClass().getDeclaredField("introspector");
- f.setAccessible(true);
- f.set(server, new APIMBeanIntrospector());
- } catch (Exception e) {
- logger.warning(
- "Failed setting new interceptor" + e.getMessage());
- }
- }
- super.setMBeanServer(server);
+ @Override
+ public ObjectInstance createMBean(String className, ObjectName name) throws ReflectionException,
+ InstanceAlreadyExistsException, MBeanRegistrationException, MBeanException, NotCompliantMBeanException {
+ return server.createMBean(className, name);
}
- public ObjectName apiNormalizeObjectName(ObjectName name) {
- try {
- Class[] cArg = new Class[1];
- cArg[0] = ObjectName.class;
- Method met = MX4JMBeanServer.class
- .getDeclaredMethod("normalizeObjectName", cArg);
- met.setAccessible(true);
- return (ObjectName) met.invoke((MX4JMBeanServer) getMBeanServer(),
- name);
- } catch (NoSuchMethodException | SecurityException | IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {
- // TODO Auto-generated catch block
- return null;
- }
+ @Override
+ public ObjectInstance createMBean(String className, ObjectName name, ObjectName loaderName)
+ throws ReflectionException, InstanceAlreadyExistsException, MBeanRegistrationException, MBeanException,
+ NotCompliantMBeanException, InstanceNotFoundException {
+ return server.createMBean(className, name, loaderName);
+ }
+
+ @Override
+ public ObjectInstance createMBean(String className, ObjectName name, Object[] params, String[] signature)
+ throws ReflectionException, InstanceAlreadyExistsException, MBeanRegistrationException, MBeanException,
+ NotCompliantMBeanException {
+ return server.createMBean(className, name, params, signature);
+ }
+
+ @Override
+ public ObjectInstance createMBean(String className, ObjectName name, ObjectName loaderName, Object[] params,
+ String[] signature) throws ReflectionException, InstanceAlreadyExistsException, MBeanRegistrationException,
+ MBeanException, NotCompliantMBeanException, InstanceNotFoundException {
+ return server.createMBean(className, name, loaderName, params, signature);
+ }
+
+ @Override
+ public ObjectInstance registerMBean(Object object, ObjectName name)
+ throws InstanceAlreadyExistsException, MBeanRegistrationException, NotCompliantMBeanException {
+ return server.registerMBean(object, name);
+ }
+
+ @Override
+ public void unregisterMBean(ObjectName name) throws InstanceNotFoundException, MBeanRegistrationException {
+ server.unregisterMBean(name);
+ }
+
+ @Override
+ public ObjectInstance getObjectInstance(ObjectName name) throws InstanceNotFoundException {
+ checkRegistrations(name);
+ return server.getObjectInstance(name);
}
@Override
public Set queryNames(ObjectName name, QueryExp query) {
- if (name == null) {
- return super.queryNames(name, query);
+ checkRegistrations(name);
+ return server.queryNames(name, query);
+ }
+
+ @Override
+ public Set queryMBeans(ObjectName name, QueryExp query) {
+ checkRegistrations(name);
+ return server.queryMBeans(name, query);
+ }
+
+ @Override
+ public boolean isRegistered(ObjectName name) {
+ checkRegistrations(name);
+ return server.isRegistered(name);
+ }
+
+ @Override
+ public Integer getMBeanCount() {
+ return server.getMBeanCount();
+ }
+
+ @Override
+ public Object getAttribute(ObjectName name, String attribute)
+ throws MBeanException, AttributeNotFoundException, InstanceNotFoundException, ReflectionException {
+ checkRegistrations(name);
+ return server.getAttribute(name, attribute);
+ }
+
+ @Override
+ public AttributeList getAttributes(ObjectName name, String[] attributes)
+ throws InstanceNotFoundException, ReflectionException {
+ checkRegistrations(name);
+ return server.getAttributes(name, attributes);
+ }
+
+ @Override
+ public void setAttribute(ObjectName name, Attribute attribute) throws InstanceNotFoundException,
+ AttributeNotFoundException, InvalidAttributeValueException, MBeanException, ReflectionException {
+ checkRegistrations(name);
+ server.setAttribute(name, attribute);
+ }
+
+ @Override
+ public AttributeList setAttributes(ObjectName name, AttributeList attributes)
+ throws InstanceNotFoundException, ReflectionException {
+ checkRegistrations(name);
+ return server.setAttributes(name, attributes);
+ }
+
+ @Override
+ public Object invoke(ObjectName name, String operationName, Object[] params, String[] signature)
+ throws InstanceNotFoundException, MBeanException, ReflectionException {
+ checkRegistrations(name);
+ return server.invoke(name, operationName, params, signature);
+ }
+
+ @Override
+ public String getDefaultDomain() {
+ return server.getDefaultDomain();
+ }
+
+ @Override
+ public String[] getDomains() {
+ return server.getDomains();
+ }
+
+ @Override
+ public void addNotificationListener(ObjectName name, NotificationListener listener, NotificationFilter filter,
+ Object handback) throws InstanceNotFoundException {
+ server.addNotificationListener(name, listener, filter, handback);
+ }
+
+ @Override
+ public void addNotificationListener(ObjectName name, ObjectName listener, NotificationFilter filter,
+ Object handback) throws InstanceNotFoundException {
+ server.addNotificationListener(name, listener, filter, handback);
+ }
+
+ @Override
+ public void removeNotificationListener(ObjectName name, ObjectName listener)
+ throws InstanceNotFoundException, ListenerNotFoundException {
+ server.removeNotificationListener(name, listener);
+ }
+
+ @Override
+ public void removeNotificationListener(ObjectName name, ObjectName listener, NotificationFilter filter,
+ Object handback) throws InstanceNotFoundException, ListenerNotFoundException {
+ server.removeNotificationListener(name, listener, filter, handback);
+ }
+
+ @Override
+ public void removeNotificationListener(ObjectName name, NotificationListener listener)
+ throws InstanceNotFoundException, ListenerNotFoundException {
+ server.removeNotificationListener(name, listener);
+ }
+
+ @Override
+ public void removeNotificationListener(ObjectName name, NotificationListener listener, NotificationFilter filter,
+ Object handback) throws InstanceNotFoundException, ListenerNotFoundException {
+ server.removeNotificationListener(name, listener, filter, handback);
+ }
+
+ @Override
+ public MBeanInfo getMBeanInfo(ObjectName name)
+ throws InstanceNotFoundException, IntrospectionException, ReflectionException {
+ checkRegistrations(name);
+ return server.getMBeanInfo(name);
+ }
+
+ @Override
+ public boolean isInstanceOf(ObjectName name, String className) throws InstanceNotFoundException {
+ return server.isInstanceOf(name, className);
+ }
+
+ @Override
+ public Object instantiate(String className) throws ReflectionException, MBeanException {
+ return server.instantiate(className);
+ }
+
+ @Override
+ public Object instantiate(String className, ObjectName loaderName)
+ throws ReflectionException, MBeanException, InstanceNotFoundException {
+ return server.instantiate(className, loaderName);
+ }
+
+ @Override
+ public Object instantiate(String className, Object[] params, String[] signature)
+ throws ReflectionException, MBeanException {
+ return server.instantiate(className, params, signature);
+ }
+
+ @Override
+ public Object instantiate(String className, ObjectName loaderName, Object[] params, String[] signature)
+ throws ReflectionException, MBeanException, InstanceNotFoundException {
+ return server.instantiate(className, loaderName, params, signature);
+ }
+
+ @Override
+ @Deprecated
+ public ObjectInputStream deserialize(ObjectName name, byte[] data)
+ throws InstanceNotFoundException, OperationsException {
+ return server.deserialize(name, data);
+ }
+
+ @Override
+ @Deprecated
+ public ObjectInputStream deserialize(String className, byte[] data)
+ throws OperationsException, ReflectionException {
+ return server.deserialize(className, data);
+ }
+
+ @Override
+ @Deprecated
+ public ObjectInputStream deserialize(String className, ObjectName loaderName, byte[] data)
+ throws InstanceNotFoundException, OperationsException, ReflectionException {
+ return server.deserialize(className, loaderName, data);
+ }
+
+ @Override
+ public ClassLoader getClassLoaderFor(ObjectName mbeanName) throws InstanceNotFoundException {
+ return server.getClassLoaderFor(mbeanName);
+ }
+
+ @Override
+ public ClassLoader getClassLoader(ObjectName loaderName) throws InstanceNotFoundException {
+ return server.getClassLoader(loaderName);
+ }
+
+ @Override
+ public ClassLoaderRepository getClassLoaderRepository() {
+ return server.getClassLoaderRepository();
+ }
+
+ static final Pattern tables = Pattern.compile("^(ColumnFamil(ies|y)|(Index)?Tables?)$");
+
+ private boolean checkRegistrations(ObjectName name) {
+ if (name != null && server.isRegistered(name)) {
+ return false;
}
- if (name.getCanonicalKeyPropertyListString()
- .contains("ColumnFamilies")) {
- ColumnFamilyStore.checkRegistration();
- } else if (name.getCanonicalKeyPropertyListString()
- .contains("Stream")) {
- StreamingMetrics.checkRegistration();
- }
- ObjectName no = apiNormalizeObjectName(name);
- Hashtable patternProps = no.getKeyPropertyList();
- boolean paternFound = false;
- for (Iterator j = patternProps.entrySet().iterator(); j.hasNext();) {
- Map.Entry entry = (Map.Entry) j.next();
- String patternValue = (String) entry.getValue();
- if (patternValue.contains("*")) {
- paternFound = true;
- break;
+
+ boolean result = false;
+
+ try {
+ String type = name != null ? name.getKeyProperty("type") : null;
+ if (type == null || tables.matcher(type).matches()) {
+ result |= ColumnFamilyStore.checkRegistration(client, server);
}
- }
- if (paternFound) {
- Set res = new HashSet();
- for (ObjectName q : (Set) super.queryNames(null,query)) {
- if (Utils.wildcardMatch(name.getDomain(), q.getDomain())) {
- Hashtable props = q.getKeyPropertyList();
- boolean found = true;
- for (Iterator j = patternProps.entrySet().iterator(); j
- .hasNext();) {
- Map.Entry entry = (Map.Entry) j.next();
- String patternKey = (String) entry.getKey();
- String patternValue = (String) entry.getValue();
- if (props.containsKey(patternKey)) {
- if (!Utils.wildcardMatch(patternValue,
- props.get(patternKey).toString())) {
- found = false;
- break;
- }
- } else {
- found = false;
- break;
- }
- }
- if (found) {
- res.add(q);
- }
- }
+ if (type == null || StreamingMetrics.TYPE_NAME.equals(type)) {
+ result |= StreamingMetrics.checkRegistration(client, server);
}
- return res;
+ } catch (MalformedObjectNameException | UnknownHostException e) {
+ // TODO: log
}
- return super.queryNames(name, query);
+ return result;
}
}
\ No newline at end of file