org.apdplat.platform.util.ReflectionUtils.java Source code

Java tutorial

Introduction

Here is the source code for org.apdplat.platform.util.ReflectionUtils.java

Source

/**
 * 
 * APDPlat - Application Product Development Platform
 * Copyright (c) 2013, ??, yang-shangchuan@qq.com
 * 
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 * 
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 * 
 */

package org.apdplat.platform.util;

import org.apdplat.platform.log.APDPlatLogger;
import java.io.File;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.net.URL;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import org.apache.commons.lang.ArrayUtils;
import org.apache.commons.lang.StringUtils;
import org.apdplat.platform.log.APDPlatLoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.util.Assert;

/**
 * ??
 * @author ??
 */
public class ReflectionUtils {
    private static final APDPlatLogger LOG = APDPlatLoggerFactory.getAPDPlatLogger(ReflectionUtils.class);

    private ReflectionUtils() {
    };

    /**
     * ???
     */
    public static List<Class<?>> getAssignedClass(Class<?> cls, List<Class<?>> clses) {
        List<Class<?>> classes = new ArrayList<>();
        for (Class<?> c : clses) {
            if (cls.isAssignableFrom(c) && !cls.equals(c)) {
                classes.add(c);
            }
        }
        return classes;
    }

    /**
     * ???
     */
    public static List<Class<?>> getClasses(Class<?> cls) throws ClassNotFoundException {
        String pk = cls.getPackage().getName();
        String path = pk.replace('.', '/');
        ClassLoader classloader = Thread.currentThread().getContextClassLoader();
        URL url = classloader.getResource(path);
        return getClasses(new File(url.getFile()), pk, null);
    }

    /**
     * ??Package?<code>outsides</code>
     */
    public static List<Class<?>> getClasses(File dir, String pk, String[] outsides) throws ClassNotFoundException {
        LOG.debug("  Dir: {}, PK: {}", new Object[] { dir, pk });
        List<Class<?>> classes = new ArrayList<>();
        if (!dir.exists()) {
            return classes;
        }
        String thisPk = StringUtils.isBlank(pk) ? "" : pk + ".";
        for (File f : dir.listFiles()) {
            if (f.isDirectory()) {
                classes.addAll(getClasses(f, thisPk + f.getName(), outsides));
            }
            String name = f.getName();
            if (name.endsWith(".class")) {
                Class<?> clazz = null;
                String clazzName = thisPk + name.substring(0, name.length() - 6);
                LOG.debug("Class: {}", clazzName);
                if (outsides == null || outsides.length == 0 || !ArrayUtils.contains(outsides, clazzName)) {
                    try {
                        clazz = Class.forName(clazzName);
                    } catch (Throwable e) {
                        LOG.error("", e);
                    }
                    if (clazz != null) {
                        classes.add(clazz);
                    }
                }
            }
        }
        return classes;
    }

    /**
     *
     * @param <T>
     * @param instance
     * @return
     */
    @SuppressWarnings("unchecked")
    public static <T> T cloneInstance(T instance) {
        Class<T> cls = (Class<T>) instance.getClass();
        T newIns = (T) BeanUtils.instantiateClass(cls);
        BeanUtils.copyProperties(instance, newIns);
        return newIns;
    }

    /**
     * Class.getSimpleName()?javassist??
     *
     * @see Class#getSimpleName()
     */
    public static String getSimpleSurname(Class<?> clazz) {
        if (clazz == null) {
            return null;
        }
        return StringUtils.substringBefore(clazz.getSimpleName(), "_$$_");
    }

    /**
     * Class.getName()?javassist??
     *
     * @see Class#getName()
     */
    public static String getSurname(Class<?> clazz) {
        if (clazz == null) {
            return null;
        }
        return StringUtils.substringBefore(clazz.getName(), "_$$_");
    }

    /**
     * ?,private/protected,??getter.
     */
    public static Object getFieldValue(final Object object, final Field field) {
        makeAccessible(field);

        Object result = null;
        try {
            result = field.get(object);
        } catch (IllegalAccessException e) {
            LOG.error("??{}", e.getMessage());
        }
        return result;
    }

    /**
     * ?,private/protected,??getter.
     */
    public static Object getFieldValue(final Object object, final String fieldName) {
        try {
            Field field = getDeclaredField(object, fieldName);

            if (field == null) {
                throw new IllegalArgumentException(
                        "Could not find field [" + fieldName + "] on target [" + object + "]");
            }
            return getFieldValue(object, field);
        } catch (Exception e) {
            String methodName = "get" + Character.toUpperCase(fieldName.charAt(0)) + fieldName.substring(1);
            try {
                Method method = object.getClass().getMethod(methodName);
                return method.invoke(object);
            } catch (NoSuchMethodException | SecurityException | IllegalAccessException | IllegalArgumentException
                    | InvocationTargetException ex) {
                LOG.error("Could not exec method [" + methodName + "] on target [" + object + "]", ex);
            }
        }
        return null;
    }

    /**
     * ??,Class?.
     *
     * @param clazz The class to introspect
     * @return the first generic declaration, or Object.class if cannot be determined
     */
    @SuppressWarnings("unchecked")
    public static <T> Class<T> getSuperClassGenricType(final Class clazz) {
        return getSuperClassGenricType(clazz, 0);
    }

    /**
     * ??,Class?.
     *
     * @param clazz clazz The class to introspect
     * @param index the Index of the generic ddeclaration,start from 0.
     * @return the index generic declaration, or Object.class if cannot be determined
     */
    @SuppressWarnings("unchecked")
    public static Class getSuperClassGenricType(final Class clazz, final int index) {

        Type genType = clazz.getGenericSuperclass();

        if (!(genType instanceof ParameterizedType)) {
            LOG.warn(clazz.getSimpleName() + "'s superclass not ParameterizedType");
            return Object.class;
        }

        Type[] params = ((ParameterizedType) genType).getActualTypeArguments();

        if (index >= params.length || index < 0) {
            LOG.warn("Index: " + index + ", Size of " + clazz.getSimpleName() + "'s Parameterized Type: "
                    + params.length);
            return Object.class;
        }
        if (!(params[index] instanceof Class)) {
            LOG.warn(clazz.getSimpleName() + " not set the actual class on superclass generic parameter");
            return Object.class;
        }
        return (Class) params[index];
    }

    /**
     * ,private/protected,??setter.
     */
    public static <T> void setFieldValue(final T object, final Field field, final Object value) {
        makeAccessible(field);

        try {
            field.set(object, value);
        } catch (IllegalAccessException e) {
            LOG.error("??:{}", e.getMessage());
        }
    }

    /**
     * ,private/protected,??setter.
     */
    public static <T> void setFieldValue(final T object, final String fieldName, final Object value) {
        try {
            Field field = getDeclaredField(object, fieldName);

            if (field == null) {
                throw new IllegalArgumentException(
                        "Could not find field [" + fieldName + "] on target [" + object + "]");
            }
            setFieldValue(object, field, value);
        } catch (Exception e) {
            String methodName = "set" + Character.toUpperCase(fieldName.charAt(0)) + fieldName.substring(1);
            try {
                Method method = object.getClass().getMethod(methodName, value.getClass());
                method.invoke(object, value);
            } catch (NoSuchMethodException | SecurityException | IllegalAccessException | IllegalArgumentException
                    | InvocationTargetException ex) {
                LOG.error("Could not exec method [" + methodName + "] on target [" + object + "]", ex);
            }
        }
    }

    /**
     * ?,?DeclaredField.
     */
    public static Field getDeclaredField(final Object object, final String fieldName) {
        Assert.notNull(object, "object?");
        Assert.hasText(fieldName, "fieldName");
        for (Class<?> superClass = object.getClass(); superClass != Object.class; superClass = superClass
                .getSuperclass()) {
            try {
                return superClass.getDeclaredField(fieldName);
            } catch (NoSuchFieldException e) {
                // Field??,?
                //e.printStackTrace();
            }
        }
        return null;
    }

    public static List<Field> getDeclaredFields(final Object object) {
        Assert.notNull(object, "object?");
        List<Field> fields = new ArrayList<>();
        for (Class<?> superClass = object.getClass(); superClass != Object.class; superClass = superClass
                .getSuperclass()) {
            Field[] f = superClass.getDeclaredFields();
            fields.addAll(Arrays.asList(f));
        }
        return fields;
    }

    /**
     * ?,?DeclaredField.
     */
    protected static void makeAccessible(final Field field) {
        if (!Modifier.isPublic(field.getModifiers())
                || !Modifier.isPublic(field.getDeclaringClass().getModifiers())) {
            field.setAccessible(true);
        }
    }
}