com.addthis.basis.jmx.DynamicMBeanImpl Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of basis Show documentation
Show all versions of basis Show documentation
AddThis core java classes
/*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.addthis.basis.jmx;
import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import javax.management.Attribute;
import javax.management.AttributeList;
import javax.management.AttributeNotFoundException;
import javax.management.DynamicMBean;
import javax.management.IntrospectionException;
import javax.management.InvalidAttributeValueException;
import javax.management.JMException;
import javax.management.MBeanAttributeInfo;
import javax.management.MBeanException;
import javax.management.MBeanInfo;
import javax.management.MBeanOperationInfo;
import javax.management.ReflectionException;
/**
* Implementation of DynamicMBean over a target object and information
* about methods of the object that should be exposed. This information
* comes either from formally declared interfaces, or simply from method
* names. NOTE: this implementation does NOT support overloaded methods,
* so if you have any, results will be unpredictable.
*/
public class DynamicMBeanImpl implements DynamicMBean {
Object target;
Map methods;
MBeanInfo info;
public DynamicMBeanImpl(Object obj, Collection> ifcs, Collection names)
throws IntrospectionException {
this.target = obj;
this.methods = new HashMap<>();
// we store methods in a map with keys like this: methodName/N, where
// N is the number of args in the method (we don't support overloading,
// so we don't care about argument types
if (ifcs != null) {
for (Class> ifc : ifcs) {
for (Method method : ifc.getMethods()) {
if (method.getDeclaringClass() != Object.class) {
String key = method.getName() + "/" + method.getParameterTypes().length;
if (!methods.containsKey(key)) {
methods.put(key, method);
}
}
}
}
}
if (names != null && names.size() > 0) {
for (Method method : target.getClass().getMethods()) {
if (names.contains(method.getName()) && method.getDeclaringClass() != Object.class) {
String key = method.getName() + "/" + method.getParameterTypes().length;
if (!methods.containsKey(key)) {
methods.put(key, method);
}
}
}
}
// once we know about all our exposed methods, we can assemble
// our MBeanInfo. all known methods are exposed as operations,
// and ones that looks like getters/setters define attributes.
List ops = new LinkedList<>();
for (Method method : methods.values()) {
ops.add(new MBeanOperationInfo(null, method));
}
List atts = new LinkedList<>();
for (String key : methods.keySet()) {
if (key.startsWith("get") && key.endsWith("/0")) {
String name = key.substring(3, key.indexOf("/"));
Method getter = methods.get(key);
Method setter = methods.get("set" + name + "/1");
atts.add(new MBeanAttributeInfo(name, null, getter, setter));
}
}
MBeanOperationInfo[] o = ops.toArray(new MBeanOperationInfo[ops.size()]);
MBeanAttributeInfo[] a = atts.toArray(new MBeanAttributeInfo[atts.size()]);
info = new MBeanInfo(target.getClass().getName(), null, a, null, o, null);
}
@Override
public Object getAttribute(String att)
throws AttributeNotFoundException, MBeanException, ReflectionException {
Method getter = methods.get("get" + att + "/0");
if (getter == null) {
throw new ReflectionException(null, "no getter for " + att);
}
try {
return getter.invoke(target);
} catch (Exception e) {
throw new MBeanException(e, "error getting att " + att);
}
}
@Override
public AttributeList getAttributes(String[] atts) {
AttributeList list = new AttributeList();
for (String att : atts) {
try {
list.add(new Attribute(att, getAttribute(att)));
} catch (JMException e) {
}
}
return list;
}
@Override
public MBeanInfo getMBeanInfo() {
return info;
}
@Override
public Object invoke(String name, Object[] params, String[] signature)
throws MBeanException, ReflectionException {
String text = name + "(" + Arrays.toString(signature) + ")";
Method method = methods.get(name + "/" + signature.length);
if (method == null) {
throw new ReflectionException(null, "no such method: " + text);
}
try {
return method.invoke(target, params);
} catch (Exception e) {
throw new MBeanException(e, "error invoking method " + text);
}
}
@Override
public void setAttribute(Attribute att)
throws AttributeNotFoundException, InvalidAttributeValueException, MBeanException, ReflectionException {
Method setter = methods.get("set" + att.getName() + "/1");
if (setter == null) {
throw new ReflectionException(null, "no setter for " + att);
}
try {
setter.invoke(target, att.getValue());
} catch (Exception e) {
throw new MBeanException(e, "error setting att " + att);
}
}
@Override
public AttributeList setAttributes(AttributeList atts) {
AttributeList list = new AttributeList();
for (Attribute att : atts.asList()) {
try {
setAttribute(att);
list.add(att);
} catch (JMException e) {
}
}
return list;
}
}