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

org.beanfabrics.util.ReflectionUtil Maven / Gradle / Ivy

Go to download

Beanfabrics is a component framework for building Java desktop applications according to the Presentation Model Pattern with Swing.

There is a newer version: 1.5.0
Show newest version
/*
 * Beanfabrics Framework Copyright (C) by Michael Karneim, beanfabrics.org
 * Use is subject to license terms. See license.txt.
 */
// TODO javadoc - remove this comment only when the class and all non-public
// methods and fields are documented
package org.beanfabrics.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.Member;
import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.Collection;
import java.util.LinkedList;
import java.util.List;
import java.util.Properties;

import org.beanfabrics.log.Logger;
import org.beanfabrics.log.LoggerFactory;

/**
 * The ReflectionUtil is a utility class for doing reflection.
 * 
 * @author Michael Karneim
 */
public class ReflectionUtil {
    private final static Logger LOG = LoggerFactory.getLogger(ReflectionUtil.class);
    private static int callCount = 0;

    public interface FieldFilter {
        boolean accept(Field field);
    }

    public interface MethodFilter {
        boolean accept(Method method);
    }

    /**
     * Returns all declared fields of the given {@link Class} and it's
     * superclasses.
     */
    public static List getAllFields(Class cls) {
        LinkedList result = new LinkedList();
        findAllFields(cls, result);
        return result;
    }

    /**
     * Returns all declared fields of the given {@link Class} and it's
     * superclasses that have the given name and are assignable to the given
     * type.
     * 
     * @param cls the class that owns the returned fields
     * @param fieldName name of the returned fields or null for no
     *            name filtering
     * @param fieldType the generic type of the returned fields or
     *            null for no type filtering
     * @return all declared fields that match the given filter arguments
     */
    public static List getAllFields(Class cls, final String fieldName, final Class fieldType) {
        LinkedList result = new LinkedList();
        findAllFields(cls, result, new FieldFilter() {
            public boolean accept(Field field) {
                return (fieldName == null || fieldName.equals(field.getName())) && (fieldType == null || fieldType.isAssignableFrom(field.getType()));
            }
        });
        return result;
    }

    private static void findAllFields(Class cls, Collection result) {
        findAllFields(cls, result, null);
    }

    private static void findAllFields(Class cls, Collection result, FieldFilter filter) {
        Field[] declFields = cls.getDeclaredFields();
        for (Field f : declFields) {
            if (filter == null || filter.accept(f)) {
                result.add(f);
            }
        }
        Class superCls = cls.getSuperclass();
        if (superCls != null) {
            findAllFields(superCls, result, filter);
        }

        // Ugh! We don't have (non static) fields in interfaces, have we??
        //        Class[] interfaces = cls.getInterfaces();
        //        for (Class i : interfaces) {
        //        	findAllFields( i, result, filter);
        //		  }
    }

    public static List getAllFields(Class cls, final Class annoType) {
        LinkedList result = new LinkedList();
        findAllFields(cls, result, new FieldFilter() {
            public boolean accept(Field field) {
                Annotation anno = field.getAnnotation(annoType);
                return (anno != null);
            }
        });
        return result;
    }

    /**
     * Returns all declared members of the given {@link Class} and it's
     * superclasses.
     * 
     * @param cls the class of which to search the members
     */
    public static List getAllMembers(Class cls) {
        LinkedList result = new LinkedList();
        findAllMethods(cls, result);
        findAllFields(cls, result);
        return result;
    }

    /**
     * Returns all declared methods of the given {@link Class} and it's
     * superclasses.
     * 
     * @param cls the class of which to search the methods
     */
    public static List getAllMethods(Class cls) {
        LinkedList result = new LinkedList();
        findAllMethods(cls, result);
        return result;
    }

    private static void findAllMethods(Class cls, Collection result) {
        Method[] declMethods = cls.getDeclaredMethods();
        for (Method m : declMethods) {
            if (result.contains(m) == false) {
                result.add(m);
            }
        }
        Class superCls = cls.getSuperclass();
        if (superCls != null) {
            findAllMethods(superCls, result);
        }
        Class[] interfaces = cls.getInterfaces();
        for (Class i : interfaces) {
            findAllMethods(i, result);
        }
    }

    /**
     * Returns all declared methods of the given {@link Class} and it's
     * superclasses that have the given name and have a return type assignable
     * to the given type.
     * 
     * @param cls the class that owns the returned methods
     * @param methodName name of the returned methods or null for
     *            no name filtering
     * @param parameterTypes the parameter types of the returned methods or
     *            null for no parameter types filtering
     * @param returnType the generic type of the returned methods or
     *            null for no type filtering
     * @return all declared methods that match the given filter arguments
     */
    public static Collection getAllMethods(Class cls, final String methodName, final Class[] parameterTypes, final Class returnType) {
        LinkedList result = new LinkedList();
        findAllMethods(cls, result, new MethodFilter() {
            public boolean accept(Method method) {
                return (methodName == null || methodName.equals(method.getName())) && (returnType == null || returnType.isAssignableFrom(method.getReturnType()))
                        && (parameterTypes == null || Arrays.equals(parameterTypes, method.getParameterTypes()));
            }
        });
        return result;
    }

    /**
     * Returns all Methods of the given {@link Class} and it's superclasses
     * which are annotated with the given annotationType.
     * 
     * @param cls the class of which to search the methods
     * @param annotationType the annotation type which mark methods to be
     *            contained in the result
     */
    public static List getAllMethods(Class cls, Class annotationType) {
        LinkedList result = new LinkedList();
        findAllMethods(cls, annotationType, result);
        return result;
    }

    private static void findAllMethods(Class cls, Collection result, MethodFilter filter) {
        Method[] declMethods = cls.getDeclaredMethods();
        for (Method f : declMethods) {
            if (filter == null || filter.accept(f)) {
                result.add(f);
            }
        }
        Class superCls = cls.getSuperclass();
        if (superCls != null) {
            findAllMethods(superCls, result, filter);
        }
        Class[] interfaces = cls.getInterfaces();
        for (Class i : interfaces) {
            findAllMethods(i, result, filter);
        }
    }

    private static void findAllMethods(Class cls, Class annoType, Collection result) {
        Method[] declMethods = cls.getDeclaredMethods();
        for (Method m : declMethods) {
            Annotation anno = m.getAnnotation(annoType);
            if (anno != null && result.contains(m) == false) {
                result.add(m);
            }
        }
        Class superCls = cls.getSuperclass();
        if (superCls != null) {
            findAllMethods(superCls, annoType, result);
        }
        Class[] interfaces = cls.getInterfaces();
        for (Class i : interfaces) {
            findAllMethods(i, annoType, result);
        }
    }

    /**
     * Returns a {@link List} of all superclasses and all interfaces of the
     * given baseclass, including the baseclass.
     * 
     * @param baseClass
     * @return List
     */
    public static List getAllClasses(Class baseClass) {
        LinkedList result = new LinkedList();
        findAllClasses(baseClass, result);
        return result;
    }

    private static void findAllClasses(Class baseClass, LinkedList result) {
        if (result.contains(baseClass) == false) {
            result.add(baseClass);
            Class superCls = baseClass.getSuperclass();
            if (superCls != null) {
                findAllClasses(superCls, result);
            }
            Class[] interfaces = baseClass.getInterfaces();
            for (Class i : interfaces) {
                findAllClasses(i, result);
            }
        }
    }

    /**
     * Calls all methods of target that are annotated with the
     * specified annotationType.
     * 
     * @param target the Object to call the methods from
     * @param annotationType the type of the annotation marking the methods to
     *            call
     */
    public static void callAnnotatedMethods(Object target, Class annotationType) {
        Collection methods = getAllMethods(target.getClass());
        for (Method m : methods) {
            Annotation anno = m.getAnnotation(annotationType);
            if (anno != null) {
                try {
                    if (!m.isAccessible()) {
                        m.setAccessible(true);
                    }
                    m.invoke(target, (Object[])null);
                } catch (IllegalAccessException ex) {
                    throw new RuntimeException(ex);
                } catch (InvocationTargetException ex) {
                    throw new RuntimeException(ex);
                }
            }
        }
    }

    public static void setProperties(Object bean, Properties props)
        throws IllegalArgumentException, IllegalAccessException, InvocationTargetException, SecurityException, NoSuchMethodException {
        Class beanClass = bean.getClass();
        for (Object key : props.keySet()) {
            if (key instanceof String) {
                String name = (String)key;
                String value = props.getProperty(name);
                String setterMethodName = "set" + firstCharToUpperCase(name);
                Method m = beanClass.getMethod(setterMethodName, new Class[] { String.class });
                m.invoke(bean, new Object[] { value });
            }
        }
    }

    private static String firstCharToUpperCase(String text) {
        String result = Character.toUpperCase(text.charAt(0)) + text.substring(1);
        return result;
    }

    public static void setFieldValue(Object owner, Field field, Object value)
        throws IllegalArgumentException, IllegalAccessException {
        if (!field.isAccessible()) {
            field.setAccessible(true);
        }
        field.set(owner, value);
    }

    public static Object getFieldValue(Object owner, Field f)
        throws IllegalArgumentException, IllegalAccessException {
        if (!f.isAccessible()) {
            f.setAccessible(true);
        }
        Object result = f.get(owner);
        return result;
    }

    public static Object invokeMethod(Object owner, Method m, Object... args)
        throws IllegalArgumentException, IllegalAccessException, InvocationTargetException {
        callCount++;
        if (!m.isAccessible()) {
            m.setAccessible(true);
        }
        if (LOG.isDebugEnabled()) {
            if (m.getParameterTypes().length == 0) {
                LOG.debug("Calling " + format(m) + " on " + owner);
            } else if (args == null) {
                LOG.debug("Calling " + format(m) + " on " + owner + " with no arguments");
            } else {
                LOG.debug("Calling " + format(m) + " on " + owner + " with arguments: " + format(args));
            }
        }
        Object result = m.invoke(owner, args);
        return result;
    }

    private static String format(Object[] args) {
        if (args == null) {
            throw new IllegalArgumentException("args==null");
        }
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < args.length; ++i) {
            if (i > 0) {
                sb.append(", ");
            }
            sb.append(args[i]);
        }
        return sb.toString();
    }

    private static String format(Method m) {
        StringBuilder sb = new StringBuilder();
        sb.append(m.getName());
        sb.append("(");
        int count = 0;
        for (Class paramType : m.getParameterTypes()) {
            if (count > 0) {
                sb.append(", ");
            }
            sb.append(paramType.getName());
            count++;
        }
        sb.append(")");
        return sb.toString();
    }

    public static  T newInstance(Class cls)
        throws IllegalArgumentException, IllegalAccessException, InvocationTargetException, SecurityException, NoSuchMethodException, InstantiationException {
        Constructor constr = cls.getConstructor((Class[])null);
        if (!constr.isAccessible()) {
            constr.setAccessible(true);
        }
        T result = constr.newInstance((Object[])null);
        return result;
    }

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy