Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
org.jgroups.jmx.ResourceDMBean Maven / Gradle / Ivy
Go to download
This artifact provides a single jar that contains all classes required to use remote EJB and JMS, including
all dependencies. It is intended for use by those not using maven, maven users should just import the EJB and
JMS BOM's instead (shaded JAR's cause lots of problems with maven, as it is very easy to inadvertently end up
with different versions on classes on the class path).
package org.jgroups.jmx;
import org.jgroups.annotations.*;
import org.jgroups.conf.AttributeType;
import org.jgroups.logging.Log;
import org.jgroups.logging.LogFactory;
import org.jgroups.util.Util;
import javax.management.*;
import java.lang.reflect.AccessibleObject;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.function.BiConsumer;
import java.util.function.Predicate;
/**
*
* A DynamicMBean wrapping an annotated object instance and exposing attributes annotated with @ManagedAttribute and
* operations annotated with @ManagedOperation.
*
* @author Chris Mills
* @author Vladimir Blagojevic
* @author Bela Ban
* @see org.jgroups.annotations.ManagedAttribute
* @see org.jgroups.annotations.ManagedOperation
* @see org.jgroups.annotations.MBean
*
*/
public class ResourceDMBean implements DynamicMBean {
protected static final Class>[] primitives= {int.class, byte.class, short.class, long.class,
float.class, double.class, boolean.class, char.class };
protected static final List OBJECT_METHODS; // all methods of java.lang.Object
protected final boolean expose_all;
protected final Log log=LogFactory.getLog(ResourceDMBean.class);
protected final Object obj;
protected List objs;
protected final MBeanAttributeInfo[] attrInfo;
protected final MBeanOperationInfo[] opInfo;
protected final HashMap atts=new HashMap<>();
protected final List ops=new ArrayList<>();
static {OBJECT_METHODS=new ArrayList<>(Arrays.asList(Object.class.getMethods()));}
protected static final Predicate FILTER=obj -> obj.isAnnotationPresent(ManagedAttribute.class) ||
(obj.isAnnotationPresent(Property.class) && obj.getAnnotation(Property.class).exposeAsManagedAttribute());
public ResourceDMBean(Object instance) {
if(instance == null)
throw new NullPointerException("Cannot make an MBean wrapper for null instance");
this.obj=instance;
Class extends Object> c=obj.getClass();
expose_all=c.isAnnotationPresent(MBean.class) && c.getAnnotation(MBean.class).exposeAll();
findFields(instance);
findMethods(instance);
fixFields(instance);
List objects=Util.getComponents(instance);
if(objects != null) {
for(Object inst: objects) {
if(inst != null) {
if(objs == null)
objs=new ArrayList<>();
objs.add(inst);
findFields(inst);
findMethods(inst);
fixFields(inst);
}
}
}
attrInfo=new MBeanAttributeInfo[atts.size()];
int i=0;
MBeanAttributeInfo info=null;
for(AttributeEntry entry: atts.values()) {
info=entry.info;
attrInfo[i++]=info;
}
opInfo=new MBeanOperationInfo[ops.size()];
ops.toArray(opInfo);
}
public MBeanInfo getMBeanInfo() {
return new MBeanInfo(obj.getClass().getCanonicalName(), "DynamicMBean", attrInfo, null, opInfo, null);
}
public Object getAttribute(String name) {
if(name == null || name.isEmpty())
throw new NullPointerException("Invalid attribute requested " + name);
Attribute attr=getNamedAttribute(name);
return attr != null? attr.getValue() : null;
}
public void setAttribute(Attribute attribute) {
if(attribute == null || attribute.getName() == null)
throw new NullPointerException("Invalid attribute requested " + attribute);
setNamedAttribute(attribute);
}
public AttributeList getAttributes(String[] names) {
AttributeList al=new AttributeList();
for(String name: names) {
Attribute attr=getNamedAttribute(name);
if(attr != null)
al.add(attr);
else
log.warn("Did not find attribute " + name);
}
return al;
}
public AttributeList setAttributes(AttributeList list) {
AttributeList results=new AttributeList();
for(int i=0;i < list.size();i++) {
Attribute attr=(Attribute)list.get(i);
if(setNamedAttribute(attr))
results.add(attr);
else {
if(log.isWarnEnabled())
log.warn("Failed to update attribute name " + attr.getName() + " with value " + attr.getValue());
}
}
return results;
}
public Object invoke(String name, Object[] args, String[] sig) throws MBeanException, ReflectionException {
try {
Class>[] classes=new Class[sig.length];
for(int i=0;i < classes.length;i++)
classes[i]=getClassForName(sig[i]);
Method method=null;
if(objs != null) {
for(Object o: objs) {
try {
method=o.getClass().getMethod(name, classes);
}
catch(Throwable t) {
continue;
}
return method.invoke(o, args);
}
}
method=obj.getClass().getMethod(name, classes);
return method.invoke(obj, args);
}
catch(Exception e) {
throw new MBeanException(e);
}
}
public static boolean isSetMethod(Method method) {
return method.getParameterCount() == 1;
}
public static boolean isGetMethod(Method method) {
return method.getParameterTypes().length == 0 && method.getReturnType() != Void.TYPE;
}
public static boolean isIsMethod(Method method) {
return method.getParameterTypes().length == 0 &&
(method.getReturnType() == boolean.class || method.getReturnType() == Boolean.class);
}
public static void dumpStats(Object obj, final Map map) {
dumpStats(obj, "", map);
}
public static void dumpStats(Object obj, String prefix, final Map map) {
BiConsumer field_func=(f,o) -> {
String attr_name=null;
try {
f.setAccessible(true);
Object value=f.get(o);
attr_name=Util.getNameFromAnnotation(f);
if(attr_name != null && !attr_name.trim().isEmpty())
attr_name=attr_name.trim();
else
attr_name=f.getName();
if(prefix != null && !prefix.isEmpty())
attr_name=prefix + "." + attr_name;
map.put(attr_name, prettyPrint(value, f));
}
catch(Exception e) {
throw new RuntimeException(String.format("could not read value of attribute \"%s\"", attr_name), e);
}
};
BiConsumer getter_func=(m,o) -> {
String method_name=null;
if(!ResourceDMBean.isGetMethod(m))
return;
try {
Object value=m.invoke(o);
method_name=Util.getNameFromAnnotation(m);
if(method_name != null && !method_name.trim().isEmpty())
method_name=method_name.trim();
else {
String field_name=Util.methodNameToAttributeName(m.getName());
method_name=Util.attributeNameToMethodName(field_name);
}
String attributeName=Util.methodNameToAttributeName(method_name);
if(prefix != null && !prefix.isEmpty())
attributeName=prefix + "." + attributeName;
map.put(attributeName, prettyPrint(value, m));
}
catch(Exception e) {
throw new RuntimeException(String.format("could not invoke getter method \"%s\"", method_name),e);
}
};
Util.forAllFieldsAndMethods(obj, FILTER, field_func, getter_func);
}
@SuppressWarnings("MalformedFormatString")
public static String prettyPrint(Object val, AccessibleObject a) {
if(val == null) return "null";
Class> cl=val.getClass();
AttributeType type=getType(a);
if(type != null) {
switch(type) {
case BYTES:
return Util.printBytes(((Number)val).doubleValue());
case TIME:
TimeUnit unit=getTimeUnit(a);
return Util.printTime(((Number)val).doubleValue(), unit);
case SCALAR:
if(isNumeric(cl))
return String.format("%,d", val);
break;
}
}
if(isNumeric(cl))
return String.format("%d", val);
if(isFractional(cl))
return String.format("%,.2f", val);
return val.toString();
}
public static boolean isNumeric(Class> cl) {
return cl.equals(short.class) || cl.equals(Short.class) || cl.equals(int.class) || cl.equals(Integer.class)
|| cl.equals(long.class) || cl.equals(Long.class);
}
public static boolean isFractional(Class> cl) {
return cl.equals(float.class) || cl.equals(Float.class) || cl.equals(double.class) || cl.equals(Double.class);
}
protected static AttributeType getType(AccessibleObject ao) {
Property prop=ao.getAnnotation(Property.class);
if(prop != null)
return prop.type();
ManagedAttribute attr=ao.getAnnotation(ManagedAttribute.class);
return attr != null? attr.type() : null;
}
protected static TimeUnit getTimeUnit(AccessibleObject ao) {
Property prop=ao.getAnnotation(Property.class);
if(prop != null)
return prop.unit();
ManagedAttribute attr=ao.getAnnotation(ManagedAttribute.class);
return attr != null? attr.unit() : null;
}
protected static Class> getClassForName(String name) throws ClassNotFoundException {
try {
return Class.forName(name);
}
catch(ClassNotFoundException cnfe) {
//Could be a primitive - let's check
for(int i=0;i < primitives.length;i++) {
if(name.equals(primitives[i].getName())) {
return primitives[i];
}
}
}
throw new ClassNotFoundException("Class " + name + " cannot be found");
}
protected void findMethods(Object instance) {
// find all methods but don't include methods from Object class
List methods = new ArrayList<>(Arrays.asList(instance.getClass().getMethods()));
methods.removeAll(OBJECT_METHODS);
for(Method method: methods) {
// does method have @ManagedAttribute annotation?
if(method.isAnnotationPresent(ManagedAttribute.class) || method.isAnnotationPresent(Property.class)) {
exposeManagedAttribute(method, instance);
}
//or @ManagedOperation
else if (method.isAnnotationPresent(ManagedOperation.class) || expose_all){
ManagedOperation op=method.getAnnotation(ManagedOperation.class);
ops.add(new MBeanOperationInfo(op != null? op.description() : "",method));
}
}
}
/** Provides field-based getter and/or setters for all attributes in attrs if not present */
protected void fixFields(Object instance) {
for(AttributeEntry attr: atts.values()) {
if(attr.getter == null)
attr.getter=findGetter(instance, attr.name);
if(attr.setter == null)
attr.setter=findSetter(instance, attr.name);
if(attr.setter == null)
attr.setter=new NoopAccessor();
}
}
protected void exposeManagedAttribute(Method method, Object instance) {
String methodName=method.getName();
ManagedAttribute attr_annotation=method.getAnnotation(ManagedAttribute.class);
Property prop=method.getAnnotation(Property.class);
boolean expose_prop=prop != null && prop.exposeAsManagedAttribute();
boolean expose=attr_annotation != null || expose_prop;
if(!expose)
return;
boolean writable=(prop != null && prop.writable()) || (attr_annotation != null && attr_annotation.writable());
// Is name of @ManagedAttributed or @Property used?
String attr_name=attr_annotation != null? attr_annotation.name() : prop != null? prop.name() : null;
if(attr_name != null && !attr_name.trim().isEmpty())
attr_name=attr_name.trim();
else {
// getFooBar() --> foo_bar
attr_name=Util.methodNameToAttributeName(methodName);
if(!atts.containsKey(attr_name)) {
// hmm, maybe we need to look for an attribute fooBar
String tmp=Util.methodNameToJavaAttributeName(methodName);
if(atts.containsKey(tmp))
attr_name=tmp;
}
}
String descr=attr_annotation != null ? attr_annotation.description() : prop != null? prop.description() : null;
AttributeEntry attr=atts.get(attr_name);
if(attr != null) {
if(isSetMethod(method)) {
if(attr.setter != null) {
if(log.isWarnEnabled())
log.warn("setter for \"" + attr_name + "\" is already defined (new method=" + method.getName() + ")");
}
else
attr.setter=new MethodAccessor(method, instance);
}
else {
if(attr.getter != null) {
if(log.isWarnEnabled())
log.warn("getter for \"" + attr_name + "\" is already defined (new method=" + method.getName() + ")");
}
else
attr.getter=new MethodAccessor(method, instance);
}
}
else { // create a new entry in atts
boolean is_setter=isSetMethod(method);
String type=is_setter? method.getParameterTypes()[0].getCanonicalName() : method.getReturnType().getCanonicalName();
MBeanAttributeInfo info=new MBeanAttributeInfo(attr_name, type, descr, true, writable, methodName.startsWith("is"));
AttributeEntry entry=new AttributeEntry(Util.methodNameToAttributeName(methodName), info);
if(is_setter)
entry.setter(new MethodAccessor(method, instance));
else
entry.getter(new MethodAccessor(method, instance));
atts.put(attr_name, entry);
}
}
/** Finds an accessor for an attribute. Tries to find getAttrName(), isAttrName(), attrName() methods. If not
* found, tries to use reflection to get the value of attr_name. If still not found, creates a NullAccessor. */
protected static Accessor findGetter(Object target, String attr_name) {
final String name=Util.attributeNameToMethodName(attr_name);
Class> clazz=target.getClass();
Method method=Util.findMethod(target, Arrays.asList("get" + name, "is" + name, toLowerCase(name)));
if(method != null && (isGetMethod(method) || isIsMethod(method)))
return new MethodAccessor(method, target);
// 4. Find a field last_name
Field field=Util.getField(clazz, attr_name);
if(field != null)
return new FieldAccessor(field, target);
return new NoopAccessor();
}
/** Finds an accessor for an attribute. Tries to find setAttrName(), attrName() methods. If not
* found, tries to use reflection to set the value of attr_name. If still not found, creates a NullAccessor. */
public static Accessor findSetter(Object target, String attr_name) {
final String name=Util.attributeNameToMethodName(attr_name);
final String fluent_name=toLowerCase(name);
Class> clazz=target.getClass();
Class> field_type=null;
Field field=Util.getField(clazz, attr_name);
field_type=field != null? field.getType() : null;
String setter_name="set" + name;
if(field_type != null) {
Method method=Util.findMethod(target, Arrays.asList(fluent_name, setter_name), field_type);
if(method != null && isSetMethod(method))
return new MethodAccessor(method, target);
}
// Find all methods but don't include methods from Object class
List methods=new ArrayList<>(Arrays.asList(clazz.getMethods()));
methods.removeAll(OBJECT_METHODS);
for(Method method: methods) {
String method_name=method.getName();
if((method_name.equals(name) || method_name.equals(fluent_name) || method_name.equals(setter_name)) && isSetMethod(method))
return new MethodAccessor(method, target);
}
// Find a field last_name
if(field != null)
return new FieldAccessor(field, target);
return null;
}
/** Returns a string with the first letter being lowercase */
protected static String toLowerCase(String input) {
if(Character.isUpperCase(input.charAt(0)))
return input.substring(0, 1).toLowerCase() + input.substring(1);
return input;
}
protected void findFields(Object instance) {
// traverse class hierarchy and find all annotated fields
for(Class> clazz=instance.getClass(); clazz != null && clazz != Object.class; clazz=clazz.getSuperclass()) {
Field[] fields=clazz.getDeclaredFields();
for(Field field: fields) {
ManagedAttribute attr=field.getAnnotation(ManagedAttribute.class);
Property prop=field.getAnnotation(Property.class);
boolean expose_prop=prop != null && prop.exposeAsManagedAttribute();
boolean expose=attr != null || expose_prop;
if(expose) {
String fieldName=attr != null? attr.name() : (prop != null? prop.name() : null);
if(fieldName != null && fieldName.trim().isEmpty())
fieldName=field.getName();
String descr=attr != null? attr.description() : prop.description();
boolean writable=attr != null? attr.writable() : prop.writable();
MBeanAttributeInfo info=new MBeanAttributeInfo(fieldName,
field.getType().getCanonicalName(),
descr,
true,
!Modifier.isFinal(field.getModifiers()) && writable,
false);
atts.put(fieldName, new AttributeEntry(field.getName(), info));
}
}
}
}
protected Attribute getNamedAttribute(String name) {
AttributeEntry entry=atts.get(name);
if(entry != null) {
try {
return new Attribute(name, entry.getter.invoke(null));
}
catch(Exception e) {
log.warn(Util.getMessage("AttrReadFailure"), name, e);
}
}
else {
log.warn(Util.getMessage("MissingAttribute"), name);
}
return null;
}
protected boolean setNamedAttribute(Attribute attribute) {
AttributeEntry entry=atts.get(attribute.getName());
if(entry != null) {
try {
entry.setter.invoke(attribute.getValue());
return true;
}
catch(Throwable e) {
log.warn(Util.getMessage("AttrWriteFailure"), attribute.getName(), e);
}
}
else {
log.warn(Util.getMessage("MissingAttribute"), attribute.getName());
}
return false;
}
protected static class AttributeEntry {
/** The name of the field or method. Can be different from the key in atts when name in @Property or
* @ManagedAttribute was used */
protected final String name;
protected final MBeanAttributeInfo info;
protected Accessor getter;
protected Accessor setter;
protected AttributeEntry(String name, MBeanAttributeInfo info) {
this(name, info, null, null);
}
protected AttributeEntry(String name, MBeanAttributeInfo info, Accessor getter, Accessor setter) {
this.name=name;
this.info=info;
this.getter=getter;
this.setter=setter;
}
protected Accessor getter() {return getter;}
protected AttributeEntry getter(Accessor new_getter) {this.getter=new_getter; return this;}
protected Accessor setter() {return setter;}
protected AttributeEntry setter(Accessor new_setter) {this.setter=new_setter; return this;}
public String toString() {
StringBuilder sb=new StringBuilder();
sb.append("AttributeEntry[" + name);
if(getter != null)
sb.append(", getter=" + getter);
if(setter() != null)
sb.append(", setter=" + setter);
sb.append("]");
return sb.toString();
}
}
public interface Accessor {
/** Invokes a getter or setter. For the getter, new_val must be ignored (null) */
Object invoke(Object new_val) throws Exception;
}
public static class MethodAccessor implements Accessor {
protected final Method method;
protected final Object target;
public MethodAccessor(Method method, Object target) {
this.method=method;
this.target=target;
}
public Method getMethod() {return method;}
public Object invoke(Object new_val) throws Exception {
return new_val != null? method.invoke(target, new_val) : method.invoke(target);
}
public String toString() {return "method[" + method.getName() + "()]";}
}
public static class FieldAccessor implements Accessor {
protected final Field field;
protected final Object target;
public FieldAccessor(Field field, Object target) {
this.field=field;
this.target=target;
if(!field.isAccessible())
field.setAccessible(true);
}
public Field getField() {return field;}
public Object invoke(Object new_val) throws Exception {
if(new_val == null)
return field.get(target);
else {
field.set(target, new_val);
return null;
}
}
public String toString() {return "field[" + field.getName() + "]";}
}
public static class NoopAccessor implements Accessor {
public Object invoke(Object new_val) throws Exception {return null;}
public String toString() {return "NoopAccessor";}
}
}