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

org.jgroups.jmx.ReflectUtils 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).

There is a newer version: 34.0.0.Final
Show newest version
package org.jgroups.jmx;

import org.jgroups.annotations.ManagedOperation;
import org.jgroups.blocks.MethodCall;
import org.jgroups.util.Ref;
import org.jgroups.util.Util;

import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.*;

/**
 * Methods to get/set attributes and invoke operations of a given instance.
 * @author Bela Ban
 * @since  5.2
 */
public class ReflectUtils {

    /** Handles an attribute read or write */
    public static void handleAttributeAccess(Map map, String attrs, Object target) {
        if(target == null)
            return;
        List list=attrs != null? Util.parseStringList(attrs, ",") : null;

        // check if there are any attribute-sets in the list
        if(list != null) {
            for(Iterator it=list.iterator(); it.hasNext(); ) {
                String tmp=it.next();
                int index=tmp.indexOf('=');
                if(index > -1) { // an attribute write
                    it.remove();
                    String attrname=tmp.substring(0, index);
                    String attrvalue=tmp.substring(index + 1);
                    try {
                        handleAttrWrite(target, attrname, attrvalue);
                    }
                    catch(Exception e) {
                        throw new IllegalArgumentException(String.format("failed writing: %s", e));
                    }
                }
            }
        }
        Map> tmp_stats=dumpSelectedAttributes(target, list);
        convert(tmp_stats, map);
    }


    /**
     * Reads all attributes and values of the given target (annotated with
     * {@link org.jgroups.annotations.ManagedAttribute} and filters them if a non-null list of attributes is given
     * @param target The object to read the attributes from
     * @param attrs A list of attributes to match against. Example: 
bind
with match
bind_addr
, *
bind_port
etc. If
null
, all attributes will be read. * @return A map of attributes and values, keyed by the object's class */ public static Map> dumpSelectedAttributes(Object target, List attrs) { Map> retval=new HashMap<>(); Map tmp=new TreeMap<>(); dumpStats(target, tmp); if(attrs != null && !attrs.isEmpty()) { // weed out attrs not in list for(Iterator it=tmp.keySet().iterator(); it.hasNext(); ) { String attrname=it.next(); boolean found=false; for(String attr : attrs) { if(attrname.startsWith(attr)) { found=true; break; // found } } if(!found) it.remove(); } } String pname=target.getClass().getSimpleName(); retval.put(pname, tmp); return retval; } public static void dumpStats(Object obj, Map map) { ResourceDMBean.dumpStats(obj, map); // dumps attrs and operations into tmp Util.forAllComponents(obj, (o,prefix) -> ResourceDMBean.dumpStats(o, prefix, map)); } /** Prints all operations of clazz annotated with {@link ManagedOperation} */ public static String listOperations(Class clazz) { if(clazz == null) return ""; StringBuilder sb=new StringBuilder(clazz.getSimpleName()).append(":\n"); Method[] methods=Util.getAllDeclaredMethodsWithAnnotations(clazz, ManagedOperation.class); for(Method m: methods) sb.append(" ").append(methodToString(m)).append("\n"); Util.forAllComponentTypes(clazz, (cl, prefix) -> { Method[] meths=Util.getAllDeclaredMethodsWithAnnotations(cl, ManagedOperation.class); for(Method m: meths) sb.append(" ").append(prefix).append(".").append(methodToString(m)).append("\n"); }); return sb.toString(); } /** * Invokes an operation and puts the return value into map * @param map * @param operation Protocol.OperationName[args], e.g. STABLE.foo[arg1 arg2 arg3] * @param target The target object on which to invoke the operation */ public static void invokeOperation(Map map, String operation, Object target) throws Exception { if(target == null) throw new IllegalArgumentException("target object must not be null"); int args_index=operation.indexOf('['); String method_name; if(args_index != -1) method_name=operation.substring(0, args_index).trim(); else method_name=operation.trim(); String[] args=null; if(args_index != -1) { int end_index=operation.indexOf(']'); if(end_index == -1) throw new IllegalArgumentException("] not found"); List str_args=Util.parseCommaDelimitedStrings(operation.substring(args_index + 1, end_index)); Object[] strings=str_args.toArray(); args=new String[strings.length]; for(int i=0; i < strings.length; i++) args[i]=(String)strings[i]; } Ref t=new Ref<>(target); Ref method=new Ref<>(Util.findMethod(target.getClass(), method_name, args)); if(!method.isSet()) { final String[] arguments=args; // check if any of the components in this class (if it has any) has the method Util.forAllComponents(target, (o,prefix) -> { if(!method.isSet() && method_name.startsWith(prefix + ".")) { String m=method_name.substring(prefix.length() +1); try { Method meth=Util.findMethod(o.getClass(), m, arguments); if(meth != null) { method.set(meth); t.set(o); } } catch(Exception e) { } } }); } if(!method.isSet()) throw new IllegalArgumentException(String.format("method %s not found in %s", method_name, target.getClass().getSimpleName())); Object retval=invoke(method.get(), t.get(), args); if(retval != null) map.put(target.getClass().getSimpleName() + "." + method_name, retval.toString()); } public static Object invoke(Method method, Object target, String[] args) throws Exception { MethodCall call=new MethodCall(method); Object[] converted_args=null; if(args != null) { converted_args=new Object[args.length]; Class[] types=method.getParameterTypes(); for(int i=0; i < args.length; i++) converted_args[i]=Util.convert(args[i], types[i]); } return call.invoke(target, converted_args); } protected static void convert(Map> in, Map out) { if(in != null) in.entrySet().stream().filter(e -> e.getValue() != null).forEach(e -> out.put(e.getKey(), e.getValue().toString())); } public static void handleAttrWrite(Object target, String attr_name, String attr_value) throws Exception { Ref ex=new Ref<>(null); // first try attributes at the protocol level try { _handleAttrWrite(target, attr_name, attr_value); return; } catch(Exception e) { ex.set(e); } // if none are found, try components next Util.forAllComponents(target, (comp,prefix) -> { if(attr_name.startsWith(prefix + ".")) { String actual_attrname=attr_name.substring(prefix.length()+1); try { _handleAttrWrite(comp, actual_attrname, attr_value); ex.set(null); } catch(Exception e) { ex.set(e); } } }); if(ex.isSet()) throw ex.get(); } public static void _handleAttrWrite(Object target, String attr_name, String attr_value) { // 1. Try to find a field first Exception e1=null, e2=null; Field field=Util.getField(target.getClass(), attr_name); if(field != null) { Object value=Util.convert(attr_value, field.getType()); if(value != null) { try { Util.setField(field, target, value); return; } catch(Exception ex) { e1=ex; } } } // 2. Try to find a setter for X, e.g. x(type-of-x) or setX(type-of-x) ResourceDMBean.Accessor setter=ResourceDMBean.findSetter(target, attr_name); if(setter != null) { try { Class type=setter instanceof ResourceDMBean.FieldAccessor? ((ResourceDMBean.FieldAccessor)setter).getField().getType() : setter instanceof ResourceDMBean.MethodAccessor? ((ResourceDMBean.MethodAccessor)setter).getMethod().getParameterTypes()[0] : null; Object converted_value=Util.convert(attr_value, type); setter.invoke(converted_value); return; } catch(Exception ex) { e2=ex; } } // at this point, we could neither find a field (and set it successfully) nor find a setter // (and invoke it successfully) String s=String.format("failed setting %s to %s: %s", attr_name, attr_value, (e1 != null || e2 != null)? e1 + " " + e2 : "field or setter not found"); throw new IllegalArgumentException(s); } protected static String methodToString(Method m) { StringBuilder sb=new StringBuilder(m.getName()); sb.append('('); StringJoiner sj = new StringJoiner(","); for(Class parameterType : m.getParameterTypes()) sj.add(parameterType.getTypeName()); sb.append(sj); sb.append(')'); return sb.toString(); } }