android.reflect.ClazzLoader.java Source code

Java tutorial

Introduction

Here is the source code for android.reflect.ClazzLoader.java

Source

/*
 * ClazzLoader.java
 * 
 * Copyright 2011 sillar team, Inc. All rights reserved.
 * 
 * SILLAR PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
 */
package android.reflect;

import android.assist.Assert;
import android.content.Context;
import android.log.Log;
import android.support.v4.util.ArrayMap;

import java.lang.annotation.Annotation;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Enumeration;

import dalvik.system.DexClassLoader;
import dalvik.system.DexFile;

/**
 * @author sillar team
 * @version 1.0.0
 * @since 1.0.0 Handy 2013-9-2
 */
public final class ClazzLoader {
    private static final String TAG = "ClazzLoader";

    /**
     * ?
     *
     * @return
     */
    public static ArrayList<String> scanPackageClazz(Context context, ClazzNameFilter clazzNameFilter) {

        return context != null ? scanPackageClazz(context.getPackageCodePath(), clazzNameFilter) : null;
    }

    /**
     * ?
     */
    public static ArrayList<String> scanPackageClazz(String apkPath, ClazzNameFilter clazzNameFilter) {
        ArrayList<String> clazzList = null;

        if (Assert.notEmpty(apkPath)) {
            clazzList = new ArrayList<>();

            try {
                DexFile dexFile = new DexFile(apkPath);
                if (dexFile != null) {
                    Enumeration<String> entries = dexFile.entries();
                    if (entries != null) {
                        while (entries.hasMoreElements()) {
                            String clazzName = entries.nextElement();

                            if (clazzNameFilter == null || clazzNameFilter.accept(clazzName)) {
                                clazzList.add(clazzName);
                            }
                        }
                    }
                }
            } catch (Exception e) {
                Log.d(TAG, e);
            }
        }

        return clazzList;
    }

    /**
     * ?
     */
    public static ArrayMap<String, Class<?>> scanPackageClazz(Context context, ClazzFilter clazzFilter) {
        ArrayMap<String, Class<?>> clazzMap = null;

        if (context != null) {
            clazzMap = new ArrayMap<String, Class<?>>();

            try {
                DexFile dexFile = new DexFile(context.getPackageCodePath());
                if (dexFile != null) {
                    Enumeration<String> entries = dexFile.entries();
                    if (entries != null) {
                        while (entries.hasMoreElements()) {
                            String clazzName = entries.nextElement();
                            if (Assert.notEmpty(clazzName)) {
                                Class<?> clazz = ClazzLoader.forName(clazzName);
                                if (clazz != null && (clazz == null || clazzFilter.accept(clazzName, clazz))) {
                                    clazzMap.put(clazzName, clazz);
                                }
                            }
                        }
                    }
                }
            } catch (Exception e) {
                Log.d(TAG, e);
            }
        }

        return clazzMap;
    }

    /**
     * ??
     */
    public static Class<?>[] getParameterTypes(Object... objs) {
        Class<?>[] parameterTypes = null;
        if (Assert.notEmpty(objs)) {
            parameterTypes = new Class<?>[objs.length];
            for (int i = 0; i < objs.length; i++) {
                Object obj = objs[i];
                if (obj != null) {
                    parameterTypes[i] = obj.getClass();
                }
            }
        }

        return parameterTypes;
    }

    /**
     * 
     */
    public static <Z> Class<Z> forName(String className) {
        Class<Z> clazz = null;

        if (Assert.notEmpty(className)) {
            try {
                Class<?> tempClazz = null;

                ClassLoader classLoader = ClazzLoader.class.getClassLoader();
                if (classLoader != null) {
                    tempClazz = classLoader.loadClass(className);
                } else {
                    tempClazz = Class.forName(className);
                }

                if (tempClazz != null) {
                    clazz = (Class<Z>) tempClazz;
                }
            } catch (Throwable t) {
                Log.e(TAG, t);
            }
        }

        return clazz;
    }

    /**
     * .dexclass
     */
    public static <Z> Class<Z> forName(ClassLoader classLoader, String desPath, String dexPath, String className) {
        Class<Z> clazz = null;

        if (classLoader != null && Assert.notEmpty(desPath) && Assert.notEmpty(dexPath)
                && Assert.notEmpty(className)) {
            DexClassLoader dexClassLoader = null;
            try {
                dexClassLoader = new DexClassLoader(dexPath, desPath, null, classLoader);
                Class<?> tempClazz = dexClassLoader.loadClass(className);
                if (tempClazz != null) {
                    clazz = (Class<Z>) tempClazz;
                }
            } catch (Throwable t) {
                Log.e(TAG, "class: " + className);
                Log.e(TAG, t);
            }
        }

        return clazz;
    }

    /**
     * .dexclass
     */
    public static <Z> Z newInstance(ClassLoader classLoader, String desPath, String dexPath, String className,
            Object... objs) {
        Z z = null;

        Class<Z> clazz = forName(classLoader, desPath, dexPath, className);
        if (clazz != null) {
            z = newInstance(clazz, objs);
        }

        return z;
    }

    /**
     * 
     */
    public static <Z> Z newInstance(String className, Object... objs) {
        Z z = null;

        Class<?> clazz = forName(className);
        if (clazz != null) {
            try {
                z = newInstance((Class<Z>) clazz, objs);
            } catch (Throwable t) {
                Log.e(TAG, "class: " + className);
                Log.e(TAG, t);
            }
        }

        return z;
    }

    /**
     * 
     */
    public static <Z> Z newInstance(Class<Z> clazz, Object... objs) {
        Z z = null;

        if (clazz != null) {
            try {
                Constructor<Z> constructor = clazz.getConstructor(getParameterTypes(objs));
                z = constructor != null ? constructor.newInstance(objs) : clazz.newInstance();
            } catch (Throwable t) {
                Log.e(TAG, "class: " + clazz.getName());
                Log.e(TAG, t);
            }
        }

        return z;
    }

    /**
     * 
     */
    public static <O, Z> Z newInstance(O o, Class<Z> clazz, Object... objs) {
        Z z = null;

        if (clazz != null) {
            try {
                boolean isInner = clazz.isAnnotationPresent(Inner.class);
                if (isInner && o != null) {
                    int size = (Assert.notEmpty(objs) ? objs.length : 0) + 1; // 1 ?

                    Class<?>[] clazzes = new Class<?>[size];
                    clazzes[0] = o.getClass();

                    Object[] values = new Object[size];
                    values[0] = o;

                    if (Assert.notEmpty(objs)) {
                        for (int i = 0; i < objs.length; i++) {
                            Object obj = objs[i];
                            if (obj != null) {

                                clazzes[i + 1] = obj.getClass();
                                values[i + 1] = obj;
                            }
                        }
                    }

                    Constructor<Z> constructor = clazz.getConstructor(clazzes);
                    z = constructor != null ? constructor.newInstance(values) : clazz.newInstance();

                } else {
                    Constructor<Z> constructor = clazz.getConstructor(getParameterTypes(objs));
                    z = constructor != null ? constructor.newInstance(objs) : clazz.newInstance();

                }
            } catch (Throwable t) {
                Log.i(TAG, "class: " + clazz.getName());
                Log.e(TAG, t);
            }
        }

        return z;
    }

    /**
     * ??Field
     */
    public static <O> Field getField(O o, String fieldName) {

        return getField(null, o, fieldName);
    }

    /**
     * ??Field
     */
    public static <O> Field getField(Class<?> clazz, O o, String fieldName) {
        Field field = null;

        if (Assert.notEmpty(fieldName)) {
            Class<?> desClazz = clazz != null ? clazz : (o != null ? o.getClass() : null);
            while (desClazz != null && desClazz != Object.class) {
                try {
                    field = desClazz.getDeclaredField(fieldName);
                    if (field != null) {
                        field.setAccessible(true);
                    } else {
                        desClazz = desClazz.getSuperclass();
                    }
                } catch (Throwable t) {
                    Log.e(TAG, "fieldName: " + fieldName);
                    Log.e(TAG, t);
                }
            }
        }

        return field;
    }

    /**
     * ???????
     */
    public static <O, V> V getFieldValue(O o, String fieldName) {

        return getFieldValue(null, o, fieldName);
    }

    /**
     * ???????
     */
    public static <V> V getFieldValue(Class<?> clazz, String fieldName) {

        return getFieldValue(clazz, null, fieldName);
    }

    /**
     * ????
     */
    public static <O, V> V getFieldValue(Class<?> clazz, O o, String fieldName) {
        V value = null;

        if (Assert.notEmpty(fieldName)) {
            Class<?> desClazz = clazz != null ? clazz : (o != null ? o.getClass() : null);
            if (desClazz != null) {
                try {
                    value = getFieldValue(o, desClazz.getDeclaredField(fieldName));
                } catch (Throwable t) {
                    Log.e(TAG, "fieldName: " + fieldName);
                    Log.e(TAG, t);
                }
            }
        }

        return value;
    }

    /**
     * ????
     */
    public static <O, V> V getFieldValue(Field field) {

        return getFieldValue(null, field);
    }

    /**
     * ????
     */
    public static <O, V> V getFieldValue(O o, Field field) {
        V value = null;

        if (field != null) {
            try {
                field.setAccessible(true);

                value = (V) field.get(o);
            } catch (Throwable e) {
                Log.v(TAG, e);
            }
        }

        return value;
    }

    /**
     * ????
     */
    public static <O, V> void setFieldValue(O o, String fieldName, V v) {
        setFieldValue(null, o, fieldName, v);
    }

    /**
     * ??????
     */
    public static <V> void setFieldValue(Class<?> clazz, String fieldName, V v) {
        setFieldValue(clazz, null, fieldName, v);
    }

    /**
     * ????
     */
    public static <O, V> void setFieldValue(Class<?> clazz, O o, String fieldName, V v) {
        if (Assert.notEmpty(fieldName)) {
            Class<?> desClass = clazz != null ? clazz : (o != null ? o.getClass() : null);
            if (desClass != null) {
                try {
                    setFieldValue(o, desClass.getDeclaredField(fieldName), v);
                } catch (Throwable t) {
                    Log.e(TAG, t);
                }
            }
        }
    }

    /**
     * ????
     */
    public static <O, V> void setFieldValue(Field field, V v) {
        setFieldValue(null, field, v);
    }

    /**
     * ????
     */
    public static <O, V> void setFieldValue(O o, Field field, V v) {
        if (field != null) {
            try {
                field.setAccessible(true);

                if (v == null) {
                    field.set(o, null);
                } else {
                    Class<?> vType = v.getClass();
                    if (vType == Integer.TYPE) {
                        field.setInt(o, (Integer) v);
                    } else if (vType == Long.TYPE) {
                        field.setLong(o, (Long) v);
                    } else if (vType == Boolean.TYPE) {
                        field.setBoolean(o, (Boolean) v);
                    } else if (vType == Float.TYPE) {
                        field.setFloat(o, (Float) v);
                    } else if (vType == Short.TYPE) {
                        field.setShort(o, (Short) v);
                    } else if (vType == Byte.TYPE) {
                        field.setByte(o, (Byte) v);
                    } else if (vType == Double.TYPE) {
                        field.setDouble(o, (Double) v);
                    } else if (vType == Character.TYPE) {
                        field.setChar(o, (Character) v);
                    } else {
                        field.set(o, v);
                    }
                }
            } catch (Throwable t) {
                Log.e(TAG, t);
            }
        }
    }

    /**
     * ?
     */
    public static Method getSingleMethodByAnnotation(Class<?> clazz, Class<? extends Annotation> annClazz) {
        Method method = null;

        if (clazz != null && annClazz != null) {
            Method[] methods = clazz.getMethods();
            if (Assert.notEmpty(methods)) {
                for (Method m : methods) {
                    if (m != null && m.isAnnotationPresent(annClazz)) {
                        method = m;

                        break;
                    }
                }
            }
        }

        return method;
    }

    /**
     * ????
     */
    public static <V> V invoke(String className, String methodName, Object... args) {

        return invoke(forName(className), null, methodName, args);
    }

    /**
     * ????
     */
    public static <V> V invoke(Class<?> clazz, String methodName, Object... args) {

        return invoke(clazz, null, methodName, args);
    }

    /**
     * ????
     */
    public static <O, V> V invoke(O o, String methodName, Object... args) {

        return invoke(null, o, methodName, args);
    }

    /**
     * ????
     */
    public static <O, V> V invoke(Class<?> clazz, O o, String methodName, Object... args) {

        return invoke(clazz, o, methodName, getParameterTypes(args), args);
    }

    /**
     * ????
     */
    public static <O, V> V invoke(Class<?> clazz, O o, String methodName, Class<?>[] parameterTypes,
            Object[] args) {
        V v = null;

        if (Assert.notEmpty(methodName)) {
            Class<?> desClazz = clazz != null ? clazz : (o != null ? o.getClass() : null);
            if (desClazz != null) {
                try {
                    Method method = desClazz.getDeclaredMethod(methodName, parameterTypes);
                    if (method != null) {
                        method.setAccessible(true);

                        v = (V) method.invoke(o, args);
                    }
                } catch (Throwable t) {
                    Log.e(TAG, "methodName: " + methodName);
                    Log.e(TAG, t);
                }
            }
        }

        return v;
    }
}