From 4b83a9388e23c680470a7fda3e451c4d44b7e09d Mon Sep 17 00:00:00 2001 From: elcallio Date: Tue, 11 Oct 2016 14:03:17 +0200 Subject: [PATCH] Make APIMBeanServer simply wrap actual mbeanserver --- .../com/scylladb/jmx/utils/APIBuilder.java | 22 +- .../scylladb/jmx/utils/APIMBeanServer.java | 370 +++++++++++++----- 2 files changed, 272 insertions(+), 120 deletions(-) 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