All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.jgroups.stack.NonReflectiveProbeHandler 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).

The newest version!
package org.jgroups.stack;

import org.jgroups.JChannel;
import org.jgroups.JChannelProbeHandler;
import org.jgroups.annotations.ManagedAttribute;
import org.jgroups.annotations.ManagedOperation;
import org.jgroups.annotations.Property;
import org.jgroups.jmx.ResourceDMBean;
import org.jgroups.util.Util;

import java.lang.reflect.AccessibleObject;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.*;
import java.util.function.BiConsumer;
import java.util.function.Predicate;

/**
 * A {@link org.jgroups.stack.DiagnosticsHandler.ProbeHandler} that does not use reflection. Can be used instead of the
 * default ProbeHandler for commands "jmx" and "op"
 * @author Bela Ban
 * @since  4.1.0
 */
public class NonReflectiveProbeHandler extends JChannelProbeHandler {
    // List of fields and field getters. Can be used to get field values, invoke field getters to get field values
    // and set fields (via Field.set()).
    protected final Map> attrs=new LinkedHashMap<>();

    // List of fields and corresponding setters. Can be used to set values of fields
    protected final Map> setters=new LinkedHashMap<>();

    // List of operations
    protected final Map> operations=new LinkedHashMap<>();

    protected static final Predicate FILTER=obj -> obj.isAnnotationPresent(ManagedAttribute.class) ||
      (obj.isAnnotationPresent(Property.class) && obj.getAnnotation(Property.class).exposeAsManagedAttribute()) ||
      obj.isAnnotationPresent(ManagedOperation.class);

    public NonReflectiveProbeHandler(JChannel ch) {
        super(ch);
    }

    public NonReflectiveProbeHandler initialize(Protocol[] protocols) {
        return initialize(Arrays.asList(protocols));
    }

    public NonReflectiveProbeHandler initialize(Collection prots) {
        for(Protocol prot: prots) {
            String prot_name=prot.getName();
            Map m=attrs.computeIfAbsent(prot_name, k -> new TreeMap<>());

            BiConsumer field_func=(f,o) -> m.put(f.getName(), new ResourceDMBean.FieldAccessor(f, o));

            BiConsumer method_func=(method,obj) -> { // getter
                if(method.isAnnotationPresent(ManagedOperation.class)) {
                    Map tmp=operations.computeIfAbsent(prot_name, k -> new TreeMap<>());
                    tmp.put(method.getName(), new ResourceDMBean.MethodAccessor(method, obj));
                }
                else if(ResourceDMBean.isGetMethod(method)) {
                    String method_name=Util.getNameFromAnnotation(method);
                    String attributeName=Util.methodNameToAttributeName(method_name);
                    m.put(attributeName, new ResourceDMBean.MethodAccessor(method, obj));
                }
                else if(ResourceDMBean.isSetMethod(method)) { // setter
                    Map tmp=setters.computeIfAbsent(prot_name, k -> new TreeMap<>());
                    String method_name=Util.getNameFromAnnotation(method);
                    String attributeName=Util.methodNameToAttributeName(method_name);
                    tmp.put(attributeName, new ResourceDMBean.MethodAccessor(method, obj));
                }
            };

            Util.forAllFieldsAndMethods(prot, FILTER, field_func, method_func);
            List objects=prot.getComponents();
            if(objects != null) {
                for(Object obj: objects)
                    if(obj != null)
                        Util.forAllFieldsAndMethods(obj, FILTER, field_func, method_func);
            }
        }
        return this;
    }

    public String dump() {
        StringBuilder sb=new StringBuilder("attrs\n-----\n");
        for(Map.Entry> e: attrs.entrySet()) {
            sb.append(e.getKey() + ":\n");
            Map val=e.getValue();
            val.forEach((key, value) -> sb.append(key + ": " + value).append("\n"));
        }
        sb.append("\nsetters\n--------\n");
        for(Map.Entry> e: setters.entrySet()) {
            sb.append(e.getKey() + ":\n");
            Map val=e.getValue();
            val.forEach((key, value) -> sb.append(key + ": " + value).append("\n"));
        }
        sb.append("\n");
        sb.append("\noperations\n--------\n");
        for(Map.Entry> e: operations.entrySet()) {
            sb.append(e.getKey() + ":\n");
            Map val=e.getValue();
            val.forEach((key, value) -> sb.append(key + ": " + value).append("\n"));
        }
        sb.append("\n");
        return sb.toString();
    }

    @Override
    protected Map> dumpAttrsAllProtocols() {
        Map> retval=new HashMap<>();
        for(Map.Entry> e: attrs.entrySet()) {
            String protocol_name=e.getKey();
            Map val=e.getValue();
            Map map=new TreeMap<>();
            for(Map.Entry en: val.entrySet()) {
                try {
                    Object v=en.getValue().invoke(null);
                    if(v instanceof Double)
                        v=String.format("%.2f", v);
                    map.put(en.getKey(), v != null? v.toString() : "null");
                }
                catch(Exception ex) {
                    log.error("failed getting value for attribute %s.%s: %s", protocol_name, en.getKey(), ex);
                }
            }
            if(!map.isEmpty())
                retval.put(protocol_name, map);
        }
        return retval;
    }

    @Override
    protected Map> dumpAttrsSelectedProtocol(String protocol_name, List attrs) {
        Map map=this.attrs.get(protocol_name);
        if(map == null)
            return null;
        Map> retval=new HashMap<>();
        Map tmp;
        retval.put(protocol_name, tmp=new TreeMap<>());

        for(Map.Entry e: map.entrySet()) {
            String attr_name=e.getKey();
            if(attrs == null || attrs.stream().anyMatch(attr_name::startsWith)) {
                try {
                    Object v=e.getValue().invoke(null);
                    tmp.put(attr_name, v);
                }
                catch(Exception ex) {
                    log.error("failed getting value for attribute %s.%s: %s", protocol_name, attr_name, ex);
                }
            }
        }
        return retval;
    }

    protected void handleAttrWrite(String protocol_name, String attr_name, String attr_value) {
        Object converted_value=null;
        // Try to find a suitable setter first:
        Map m=setters.get(protocol_name);
        if(m != null) {
            ResourceDMBean.Accessor setter=m.get(attr_name);
            if(setter != null) {
                Class type=((ResourceDMBean.MethodAccessor)setter).getMethod().getParameterTypes()[0];
                converted_value=Util.convert(attr_value, type);
                invoke(protocol_name, setter, attr_name, converted_value);
                return;
            }
        }

        // try to find a field
        m=attrs.get(protocol_name);
        if(m == null)
            throw new RuntimeException(String.format("protocol %s not found", protocol_name));
        ResourceDMBean.Accessor setter=m.get(attr_name);
        if(setter == null)
            throw new RuntimeException(String.format("attribute %s not found in protocol %s", attr_name, protocol_name));
        if(setter instanceof ResourceDMBean.FieldAccessor) {
            converted_value=Util.convert(attr_value, ((ResourceDMBean.FieldAccessor)setter).getField().getType());
            invoke(protocol_name, setter, attr_name, converted_value);
        }
    }

    @Override
    protected Method findMethod(Protocol prot, String method_name, String[] args) throws Exception {
        Map map=operations.get(prot.getName());
        if(map == null) {
            log.error("protocol %s not found for method %s", prot.getName(), method_name);
            return null;
        }
        ResourceDMBean.MethodAccessor accessor=map.get(method_name);
        if(accessor == null) {
            log.error("method %s not found", method_name);
            return null;
        }
        return accessor.getMethod();
    }

    protected static void invoke(String protocol_name, ResourceDMBean.Accessor setter, String attr, Object value) {
        try {
            setter.invoke(value);
        }
        catch(Exception e) {
            throw new RuntimeException(String.format("setting %s=%s failed in protocol %s: %s", attr, value, protocol_name, e));
        }
    }
}