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

org.squirrelframework.foundation.util.ReflectUtils Maven / Gradle / Ivy

Go to download

foundation module of squirrel framework which provided event driven infrastructure and a finite state machine implementation.

There is a newer version: 0.3.10
Show newest version
package org.squirrelframework.foundation.util;

import java.lang.annotation.Annotation;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.List;
import java.util.Set;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.squirrelframework.foundation.exception.ErrorCodes;
import org.squirrelframework.foundation.exception.SquirrelRuntimeException;

import com.google.common.collect.Lists;
import com.google.common.collect.Sets;

public class ReflectUtils {

    private ReflectUtils() {}

    private final static Logger logger = LoggerFactory.getLogger(ReflectUtils.class);

    public static Set getAllDeclaredFields(final Class theClass) {
        Set aFields = Sets.newHashSet();
        Class aClass = theClass;
        while (aClass != null) {
            aFields.addAll(Sets.newHashSet(aClass.getDeclaredFields()));
            aClass = aClass.getSuperclass();
        }
        return aFields;
    }

    /** searches for the field in the given class and in its super classes */
    public static Field getField(Class clazz, String fieldName) {
        return getField(clazz, fieldName, clazz);
    }

    private static Field getField(Class clazz, String fieldName, Class original) {
        Field field = null;
        try {
            field = clazz.getDeclaredField(fieldName);
            if (logger.isTraceEnabled()) {
                logger.trace("found field "+fieldName+" in "+getClassNameSafe(clazz));
            }
        } catch (SecurityException e) {
            throw new SquirrelRuntimeException(e, ErrorCodes.NOT_ALLOW_ACCESS_FIELD, getClassNameSafe(clazz), fieldName);
        } catch (NoSuchFieldException e) {
            if (clazz.getSuperclass()!=null) {
                return getField(clazz.getSuperclass(), fieldName, original);
            } else {
                throw new SquirrelRuntimeException(e, ErrorCodes.FIELD_NOT_FOUND, original.getName(), fieldName);
            }
        }
        return field;
    }

    /** searches for the method in the given class and in its super classes */
    public static Method getMethod(Class clazz, String methodName, Class[] parameterTypes) {
        return getMethod(clazz, methodName, parameterTypes, clazz);
    }

    private static Method getMethod(Class clazz, String methodName, Class[] parameterTypes, Class original) {
        Method method = null;
        try {
            method = clazz.getDeclaredMethod(methodName, parameterTypes);
            if (logger.isTraceEnabled()) {
                logger.trace("found method "+getClassNameSafe(clazz)+"."+methodName+"("+Arrays.toString(parameterTypes)+")");
            }
        } catch (SecurityException e) {
            throw new SquirrelRuntimeException(e, ErrorCodes.NOT_ALLOW_ACCESS_METHOD, getClassNameSafe(clazz), methodName, getParameterTypesText(parameterTypes));
        } catch (NoSuchMethodException e) {
            if (clazz.getSuperclass()!=null) {
                return getMethod(clazz.getSuperclass(), methodName, parameterTypes, original);
            } else {
                throw new SquirrelRuntimeException(e, ErrorCodes.METHOD_NOT_FOUND, original.getName(), methodName, getParameterTypesText(parameterTypes));
            }
        }
        return method;
    }

    private static String getParameterTypesText(Class[] parameterTypes) {
        if (parameterTypes==null) return "";
        StringBuilder parameterTypesText = new StringBuilder();
        for (int i=0; i parameterType = parameterTypes[i];
            parameterTypesText.append(parameterType.getName());
            if (i!=parameterTypes.length-1) {
                parameterTypesText.append(", ");
            }
        }
        return parameterTypesText.toString();
    }
    
    public static String logMethod(Method method) {
        StringBuilder builder = new StringBuilder(method.getDeclaringClass().getSimpleName());
        builder.append('.').append(method.getName()).append('(');
        if(method.getParameterTypes()!=null) {
            for(int i=0, size=method.getParameterTypes().length; i T getAnnotation(Class theClass, Class theAnnotation) {
        T aAnnotation = null;

        if (theClass.isAnnotationPresent(theAnnotation)) {
            aAnnotation = theClass.getAnnotation(theAnnotation);
        } else {
            if (shouldInspectClass(theClass.getSuperclass())) 
                aAnnotation = getAnnotation(theClass.getSuperclass(), theAnnotation);

            if (aAnnotation == null) {
                for (Class aInt : theClass.getInterfaces()) {
                    aAnnotation = getAnnotation(aInt, theAnnotation);
                    if (aAnnotation != null) { break; }
                }
            }
        }
        return aAnnotation;
    }

    /**
     * Return whether or not the class has the given annotation.  If the class itself does not have the annotation,
     * it's super class and the interfaces it implements are checked.
     * @param theClass the class to check
     * @param theAnnotation the annotation to look for
     * @return if the class has the annotation, or one of its parents does and it "inherited" the annotation, false otherwise
     */
    public static boolean hasAnnotation(Class theClass, Class theAnnotation) {
        return getAnnotation(theClass, theAnnotation) != null;
    }

    public static List getAnnotatedMethods(
            Class targetClass, Class annotationClass) {
        List aMethods = Lists.newArrayList();

        for (Method aMethod : targetClass.getMethods()) {
            if (aMethod.getAnnotation(annotationClass) != null) {
                aMethods.add(aMethod);
            }
        }

        if (shouldInspectClass(targetClass.getSuperclass())) {
            aMethods.addAll(getAnnotatedMethods(targetClass.getSuperclass(), annotationClass));
        }

        for (Class aInterface : targetClass.getInterfaces()) {
            aMethods.addAll(getAnnotatedMethods(aInterface, annotationClass));
        }

        return aMethods;
    }

    private static boolean shouldInspectClass(final Class theClass) {
        return !Object.class.equals(theClass) && theClass != null;
    }

    public static Field[] getAnnotatedFields(
            Class targetClass, Class annotationClass) {
        List annotatedFields = Lists.newArrayList();
        Class k = targetClass;
        while(shouldInspectClass(k)) {
            for(Field f : k.getFields()) {
                if(f.getAnnotation(annotationClass)!=null) {
                    annotatedFields.add(f);
                }
            }
            k = k.getSuperclass();
        }
        return annotatedFields.toArray(new Field[0]);
    }

    public static boolean isAnnotatedWith(Object obj, Class theAnnotation) {
        if(obj instanceof Class) {
            return hasAnnotation((Class)obj, theAnnotation);
        } else if(obj instanceof Field) {
            return ((Field)obj).getAnnotation(theAnnotation)!=null;
        } else if(obj instanceof Method) {
            return ((Method)obj).getAnnotation(theAnnotation)!=null;
        } // TODO-hhe: how about annotation with parameter?
        return false;
    }

    public static Method getFirstMethodOfName(Class clazz, String name) {
        for(Method m : clazz.getMethods()) 
            if(m.getName().equals(name)) { return m; }
        return null;
    }

    public static  Constructor getConstructor(Class type, Class[] parameterTypes) {
        try {
            Constructor constructor = type.getDeclaredConstructor(parameterTypes);
            return constructor;
        } catch (NoSuchMethodException e) {
            throw new SquirrelRuntimeException(e, ErrorCodes.CONSTRUCTOR_NOT_FOUND, 
                    type.getName(), Arrays.toString(parameterTypes));
        }
    }
    
    @SuppressWarnings("unchecked")
    public static  T newInstance(String className) {
        return (T) newInstance(getClass(className), null, null);
    }

    public static  T newInstance(Class clazz) {
        return newInstance(clazz, null, null);
    }

    public static  T newInstance(Constructor constructor) {
        return newInstance(null, constructor, null);
    }

    public static  T newInstance(Constructor constructor, Object[] args) {
        return newInstance(null, constructor, args);
    }

    private static  T newInstance(Class clazz, Constructor constructor, Object[] args) {
        if ( (clazz==null) && (constructor==null) ) {
            throw new IllegalArgumentException("can't create new instance without clazz or constructor");
        }

        if (logger.isTraceEnabled()) {
            logger.trace("creating new instance for class '"+getClassNameSafe(clazz)+"' with args "+Arrays.toString(args));
        }
        if (constructor==null) {
            if (logger.isTraceEnabled()) logger.trace("getting default constructor");
            constructor = getConstructor(clazz, (Class[])null);
        }

        boolean oldAccessible = constructor.isAccessible();
        try {

            if (!constructor.isAccessible()) {
                if (logger.isTraceEnabled()) logger.trace("making constructor accessible");
                constructor.setAccessible(true);
            }
            return constructor.newInstance(args);

        } catch (Throwable t) {
            Throwable cause = (t instanceof InvocationTargetException) ? ((InvocationTargetException)t).getTargetException() : t;
            throw new SquirrelRuntimeException(cause, ErrorCodes.CONSTRUCT_NEW_INSTANCE_ERROR, getClassNameSafe(clazz), Arrays.toString(args));
        } finally {
            constructor.setAccessible(oldAccessible);
        }
    }

    public static Object getStatic(Field field) {
        return get(field, null);
    }

    public static Object get(Field field, Object object) {
        if (field==null) {
            throw new SquirrelRuntimeException(ErrorCodes.FIELD_NULL);
        }
        boolean oldAccessible = field.isAccessible();
        try {
            field.setAccessible(true);
            Object value = field.get(object);
            if (logger.isTraceEnabled()) {
                logger.trace("got value '"+value+"' from field '"+field.getName()+"'");
            }
            return value;
        } catch (Exception e) {
            throw new SquirrelRuntimeException(e, ErrorCodes.CANNOT_GET_FIELD_VALUE, field.getName());
        } finally {
            field.setAccessible(oldAccessible);
        }
    }

    public static void setStatic(Field field, Object value) {
        set(field, null, value);
    }

    public static void set(Field field, Object object, Object value) {
        if (field==null) {
            throw new SquirrelRuntimeException(ErrorCodes.FIELD_NULL);
        }
        boolean oldAccessible = field.isAccessible();
        try {
            if (logger.isTraceEnabled()) {
                logger.trace("setting field '"+field.getName()+"' to value '"+value+"'");
            }
            if (!oldAccessible) {
                if (logger.isTraceEnabled()) logger.trace("making field accessible");
                field.setAccessible(true);
            }
            field.set(object, value);
        } catch (Exception e) {
            throw new SquirrelRuntimeException(e, ErrorCodes.CANNOT_SET_FIELD_VALUE, field.getName(), value);
        } finally {
            field.setAccessible(oldAccessible);
        }
    }

    public static Object invokeStatic(Method method) {
        return invoke(method, null, new Object[0]);
    }

    public static Object invokeStatic(Method method, Object[] args) {
        return invoke(method, null, args);
    }

    public static Object invoke(Method method, Object target) {
        return invoke(method, target, new Object[0]);
    }

    public static Object invoke(Method method, Object target, Object[] args) {
        if (method==null) {
            throw new SquirrelRuntimeException(ErrorCodes.METHOD_NULL);
        }
        boolean oldAccessible = method.isAccessible();
        try {
            if (logger.isTraceEnabled()) {
                logger.trace("invoking '"+method.getName()+"' on '"+target+"' with "+Arrays.toString(args));
            }
            if (!method.isAccessible()) {
                logger.trace("making method accessible");
                method.setAccessible(true);
            }
            return method.invoke(target, args);
        } catch (InvocationTargetException e) {
            Throwable targetException = e.getTargetException();
            throw new SquirrelRuntimeException(targetException, ErrorCodes.METHOD_INVOKE_ERROR, 
                    method, Arrays.toString(args), target, targetException.getCause());
        } catch (Exception e) {
            throw new SquirrelRuntimeException(e, ErrorCodes.METHOD_INVOKE_ERROR, 
                    method, Arrays.toString(args), target, e.getMessage());
        } finally {
            method.setAccessible(oldAccessible);
        }
    }
    
    /**
     * Invoke the given callback on all fields in the target class, going up the
     * class hierarchy to get all declared fields.
     * @param clazz the target class to analyze
     * @param fc the callback to invoke for each field
     */
    public static void doWithFields(Class clazz, FieldCallback fc) throws IllegalArgumentException {
        doWithFields(clazz, fc, null);
    }

    /**
     * Invoke the given callback on all fields in the target class, going up the
     * class hierarchy to get all declared fields.
     * @param clazz the target class to analyze
     * @param fc the callback to invoke for each field
     * @param ff the filter that determines the fields to apply the callback to
     */
    public static void doWithFields(Class clazz, FieldCallback fc, FieldFilter ff)
            throws IllegalArgumentException {

        // Keep backing up the inheritance hierarchy.
        Class targetClass = clazz;
        do {
            Field[] fields = targetClass.getDeclaredFields();
            for (Field field : fields) {
                // Skip static and final fields.
                if (ff != null && !ff.matches(field)) {
                    continue;
                }
                fc.doWith(field);
            }
            targetClass = targetClass.getSuperclass();
        }
        while (targetClass != null && targetClass != Object.class);
    }
    
    /**
     * Perform the given callback operation on all matching methods of the given
     * class and superclasses.
     * 

The same named method occurring on subclass and superclass will appear * twice, unless excluded by a {@link MethodFilter}. * @param clazz class to start looking at * @param mc the callback to invoke for each method * @see #doWithMethods(Class, MethodCallback, MethodFilter) */ public static void doWithMethods(Class clazz, MethodCallback mc) throws IllegalArgumentException { doWithMethods(clazz, mc, null); } /** * Perform the given callback operation on all matching methods of the given * class and superclasses (or given interface and super-interfaces). *

The same named method occurring on subclass and superclass will appear * twice, unless excluded by the specified {@link MethodFilter}. * @param clazz class to start looking at * @param mc the callback to invoke for each method * @param mf the filter that determines the methods to apply the callback to */ public static void doWithMethods(Class clazz, MethodCallback mc, MethodFilter mf) throws IllegalArgumentException { // Keep backing up the inheritance hierarchy. Method[] methods = clazz.getDeclaredMethods(); for (Method method : methods) { if (mf != null && !mf.matches(method)) { continue; } mc.doWith(method); } if (clazz.getSuperclass() != null) { doWithMethods(clazz.getSuperclass(), mc, mf); } else if (clazz.isInterface()) { for (Class superIfc : clazz.getInterfaces()) { doWithMethods(superIfc, mc, mf); } } } /** * Returns all superclasses. */ public static Class[] getSuperclasses(Class type) { int i = 0; for (Class x = type.getSuperclass(); x != null; x = x.getSuperclass()) { i++; } Class[] result = new Class[i]; i = 0; for (Class x = type.getSuperclass(); x != null; x = x.getSuperclass()) { result[i] = x; i++; } return result; } /** * Returns true if method is user defined and not defined in Object class. */ public static boolean isUserDefinedMethod(final Method method) { return method.getDeclaringClass() != Object.class; } /** * Returns true if method is a bean property. */ public static boolean isBeanProperty(Method method) { String methodName = method.getName(); Class returnType = method.getReturnType(); Class[] paramTypes = method.getParameterTypes(); if (methodName.startsWith("get") && methodName.equals("getClass") == false) { // getter method must starts with 'get' and it is not getClass() if ((returnType != null) && (paramTypes.length == 0)) { // getter must have a return type and no arguments return true; } } else if (methodName.startsWith("is")) { // ister must starts with 'is' if ((returnType != null) && (paramTypes.length == 0)) { // ister must have return type and no arguments return true; } } else if (methodName.startsWith("set")) { // setter must start with a 'set' if (paramTypes.length == 1) { // setter must have just one argument return true; } } return false; } public static String getPackageName(final String className) { if (className==null || className.length() == 0) throw new SquirrelRuntimeException(ErrorCodes.ILLEGAL_CLASS_NAME); int index = className.lastIndexOf('.'); if (index != -1) return className.substring(0, index); return ""; } public static Class getClass(final String className) { if (className==null || className.length() == 0) throw new SquirrelRuntimeException(ErrorCodes.ILLEGAL_CLASS_NAME); try { return Class.forName(className); } catch (ClassNotFoundException e) { throw new SquirrelRuntimeException(e, ErrorCodes.CLASS_NOT_FOUND, className); } } private static String getClassNameSafe(Class maybeNullClazz) { if (maybeNullClazz == null) return null; else return maybeNullClazz.getName(); } /** * Action to take on each method. */ public interface MethodCallback { /** * Perform an operation using the given method. * @param method the method to operate on */ void doWith(Method method); } /** * Callback optionally used to filter methods to be operated on by a method callback. */ public interface MethodFilter { /** * Determine whether the given method matches. * @param method the method to check */ boolean matches(Method method); } /** * Callback interface invoked on each field in the hierarchy. */ public interface FieldCallback { /** * Perform an operation using the given field. * @param field the field to operate on */ void doWith(Field field); } /** * Callback optionally used to filter fields to be operated on by a field callback. */ public interface FieldFilter { /** * Determine whether the given field matches. * @param field the field to check */ boolean matches(Field field); } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy