package com.android.pc.ioc.core.kernel; 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.lang.reflect.Modifier; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import com.android.pc.ioc.core.kernel.KernelLang.BreakException; import com.android.pc.ioc.core.kernel.KernelLang.CallbackBreak; @SuppressWarnings({ "rawtypes", "unchecked" }) public abstract class KernelReflect { /** * @param member * @return */ public static <T extends Member> T memberStatic(T member) { return memberStatic(member, null); } /** * @param member * @param defaultValue * @return */ public static <T extends Member> T memberStatic(T member, T defaultValue) { if (member == null || !Modifier.isStatic(member.getModifiers())) { return defaultValue; } return member; } /** * @param member * @return */ public static <T extends Member> T memberAccessor(T member) { return memberAccessor(member, null); } /** * @param member * @param defaultValue * @return */ public static <T extends Member> T memberAccessor(T member, T defaultValue) { if (member == null || Modifier.isFinal(member.getModifiers()) || Modifier.isStatic(member.getModifiers())) { return defaultValue; } return member; } /** * @param cls * @param parameterTypes * @return */ public static <T> Constructor<T> constructor(Class<T> cls, Class... parameterTypes) { return declaredConstructor(cls, false, parameterTypes); } /** * @param cls * @param parameterTypes * @return */ public static <T> Constructor<T> declaredConstructor(Class<T> cls, Class... parameterTypes) { return declaredConstructor(cls, true, parameterTypes); } /** * @param cls * @param declared * @param parameterTypes * @return */ public static <T> Constructor<T> declaredConstructor(Class<T> cls, boolean declared, Class... parameterTypes) { try { Constructor<T> constructor = declared ? cls.getDeclaredConstructor(parameterTypes) : cls.getConstructor(parameterTypes); if (constructor != null) { if (declared && !constructor.isAccessible()) { constructor.setAccessible(true); } return constructor; } } catch (SecurityException e) { } catch (NoSuchMethodException e) { } return null; } /** * @param cls * @param parameterTypes * @return */ public static <T> Constructor<T> assignableConstructor(Class<T> cls, Class... parameterTypes) { return assignableConstructor(cls, false, parameterTypes); } /** * @param cls * @param declared * @param parameterTypes * @return */ public static <T> Constructor<T> assignableConstructor(Class<T> cls, boolean declared, Class... parameterTypes) { Constructor<T>[] constructors = (Constructor<T>[]) (declared ? cls.getDeclaredConstructors() : cls.getConstructors()); int similar = -2; Constructor<T> constructor = null; for (Constructor<T> structor : constructors) { if (KernelClass.isMatchableFrom(structor.getParameterTypes(), parameterTypes)) { if (!structor.isAccessible()) { if (declared) { structor.setAccessible(true); } else { continue; } } int sim = KernelClass.similar(parameterTypes, structor.getParameterTypes()); if (similar < sim) { similar = sim; constructor = structor; } } } return constructor; } /** * @param cls * @param declared * @param assignable * @param parameterTypes * @return */ public static <T> Constructor<T> assignableConstructor(Class<T> cls, boolean declared, boolean assignable, Class... parameterTypes) { return assignable ? assignableConstructor(cls, declared, parameterTypes) : declaredConstructor(cls, declared, parameterTypes); } /** * @param constructor * @param initargs * @return */ public static <T> T newInstance(Constructor<T> constructor, Object... initargs) { return newInstance(constructor, null, initargs); } /** * @param constructor * @param defaultValue * @param initargs * @return */ public static <T> T newInstance(Constructor<T> constructor, T defaultValue, Object... initargs) { if (constructor != null) { try { return constructor.newInstance(initargs); } catch (IllegalArgumentException e) { } catch (InstantiationException e) { } catch (IllegalAccessException e) { } catch (InvocationTargetException e) { } } return defaultValue; } /** * @param cls * @param name * @return */ public static Field field(Class cls, String name) { return field(cls, name, 0); } /** * @param cls * @param name * @param ancest * @return */ public static Field field(Class cls, String name, int ancest) { return declaredField(cls, name, ancest, false); } /** * @param cls * @param name * @return */ public static Field declaredField(Class cls, String name) { return declaredField(cls, name, 0); } /** * @param cls * @param name * @param ancest * @return */ public static Field declaredField(Class cls, String name, int ancest) { return declaredField(cls, name, ancest, true); } /** * @param cls * @param name * @param ancest * @param declared * @return */ public static Field declaredField(Class cls, String name, int ancest, boolean declared) { Field field = null; while (cls != null) { try { field = declared ? cls.getDeclaredField(name) : cls.getField(name); break; } catch (SecurityException e) { break; } catch (NoSuchFieldException e) { } if (ancest < 1 || ancest-- != 1) { cls = cls.getSuperclass(); } else { cls = null; } } if (field != null) { if (declared && !field.isAccessible()) { field.setAccessible(true); } } return field; } /** * @param cls * @return */ public static List<Field> fields(Class cls) { return fields(cls, 0); } /** * @param cls * @param ancest * @return */ public static List<Field> fields(Class cls, int ancest) { return declaredFields(cls, ancest, false); } /** * @param cls * @return */ public static List<Field> declaredFields(Class cls) { return declaredFields(cls, 0); } /** * @param cls * @param ancest * @return */ public static List<Field> declaredFields(Class cls, int ancest) { return declaredFields(cls, ancest, true); } /** * @param cls * @param ancest * @param declared * @return */ public static List<Field> declaredFields(Class cls, int ancest, boolean declared) { List<Field> declaredFields = new ArrayList<Field>(); while (cls != null) { Field[] fields = declared ? cls.getDeclaredFields() : cls.getFields(); for (Field field : fields) { if (declared && !field.isAccessible()) { field.setAccessible(true); } declaredFields.add(field); } if (ancest < 1 || ancest-- != 1) { cls = cls.getSuperclass(); } else { cls = null; } } return declaredFields; } /** * @param obj * @param field * @param value * @return */ public static boolean set(Object obj, Field field, Object value) { if (field != null) { try { field.setAccessible(true); field.set(obj, value); return true; } catch (IllegalArgumentException e) { } catch (IllegalAccessException e) { } } return false; } /** * @param obj * @param field * @return */ public static Object get(Object obj, Field field) { return KernelReflect.get(obj, null, field); } /** * @param obj * @param defaultValue * @param field * @return */ public static Object get(Object obj, Object defaultValue, Field field) { if (field != null) { try { return field.get(obj); } catch (IllegalArgumentException e) { } catch (IllegalAccessException e) { } } return defaultValue; } /** Class_Method_Map_Method */ protected final static Map<String, Method> Class_Method_Map_Method = new HashMap<String, Method>(); /** * @param cls * @param name * @param parameterTypes * @return */ public static Method method(Class cls, String name, Class... parameterTypes) { return method(cls, name, 0, parameterTypes); } /** * @param cls * @param name * @param ancest * @param parameterTypes * @return */ public static Method method(Class cls, String name, int ancest, Class... parameterTypes) { return declaredMethod(cls, name, ancest, false, parameterTypes); } /** * @param cls * @param name * @param parameterTypes * @return */ public static Method declaredMethod(Class cls, String name, Class... parameterTypes) { return declaredMethod(cls, name, 0, parameterTypes); } /** * @param cls * @param name * @param ancest * @param parameterTypes * @return */ public static Method declaredMethod(Class cls, String name, int ancest, Class... parameterTypes) { return declaredMethod(cls, name, ancest, true, parameterTypes); } /** * @param cls * @param name * @param ancest * @param declared * @param parameterTypes * @return */ public static Method declaredMethod(Class cls, String name, int ancest, boolean declared, Class... parameterTypes) { return assignableMethod(cls, name, ancest, declared, false, false, parameterTypes); } /** * @param cls * @param name * @param parameterTypes * @return */ public static Method assignableMethod(Class cls, String name, Class... parameterTypes) { return assignableMethod(cls, name, 0, parameterTypes); } /** * @param cls * @param name * @param ancest * @param parameterTypes * @return */ public static Method assignableMethod(Class cls, String name, int ancest, Class... parameterTypes) { return assignableMethod(cls, name, ancest, false, parameterTypes); } /** * @param cls * @param name * @param ancest * @param declared * @param parameterTypes * @return */ public static Method assignableMethod(Class cls, String name, int ancest, boolean declared, Class... parameterTypes) { return assignableMethod(cls, name, ancest, declared, true, true, parameterTypes); } /** * @param cls * @param name * @param ancest * @param declared * @param assignable * @param cacheable * @param parameterTypes * @return */ public static Method assignableMethod(Class cls, final String name, int ancest, boolean declared, boolean assignable, boolean cacheable, final Class... parameterTypes) { String class_method_key = null; if (cacheable) { class_method_key = cls.getName() + ":" + name + ":" + parameterTypes.length; Method method = Class_Method_Map_Method.get(class_method_key); if (method != null && KernelClass.isMatchableFrom(method.getParameterTypes(), parameterTypes)) { return method; } } Method method = null; while (cls != null) { if (assignable && parameterTypes.length > 0) { final List<Method> matchMethods = new ArrayList<Method>(); CallbackBreak<Method> callback = new CallbackBreak<Method>() { @Override public void doWith(Method template) throws BreakException { // TODO Auto-generated method stub if (template.getName().equals(name) && KernelClass.isMatchableFrom(template.getParameterTypes(), parameterTypes)) { for (Method method : matchMethods) { if (KernelArray.equal(method.getParameterTypes(), template.getParameterTypes())) { return; } } matchMethods.add(template); } } }; if (declared) { doWithDeclaredMethods(cls, callback); } else { doWithMethods(cls, callback); } if (matchMethods.size() > 0) { if (matchMethods.size() == 1) { method = matchMethods.get(0); } else { cacheable = false; int similar = -2; for (Method match : matchMethods) { int sim = KernelClass.similar(parameterTypes, match.getParameterTypes()); if (similar < sim) { similar = sim; method = match; } } } } } else { try { method = declared ? cls.getDeclaredMethod(name, parameterTypes) : cls.getMethod(name, parameterTypes); break; } catch (SecurityException e) { break; } catch (NoSuchMethodException e) { } } if (ancest < 1 || ancest-- != 1) { cls = cls.getSuperclass(); } else { cls = null; } } if (method != null) { if (declared && !method.isAccessible()) { method.setAccessible(true); } if (cacheable) { Class_Method_Map_Method.put(class_method_key, method); } } return method; } /** * @param obj * @param method * @param args * @return */ public static Object invoke(Object obj, Method method, Object... args) { return KernelReflect.invoke(obj, null, method, args); } /** * @param obj * @param defaultValue * @param method * @param args * @return */ public static Object invoke(Object obj, Object defaultValue, Method method, Object... args) { if (method != null) { try { return method.invoke(obj, args); } catch (IllegalArgumentException e) { } catch (IllegalAccessException e) { } catch (InvocationTargetException e) { } } return defaultValue; } /** * @param cls * @param callback */ public static void doWithClasses(Class cls, CallbackBreak<Class<?>> callback) { doWithClasses(cls, callback, null); } /** * @param cls * @param callback * @param superClass */ public static void doWithClasses(Class cls, CallbackBreak<Class<?>> callback, Class superClass) { try { while (cls != null && cls != Object.class && cls != superClass) { callback.doWith(cls); cls = cls.getSuperclass(); } } catch (BreakException e) { } } /** * @param cls * @param callback */ public static void doWithFields(Class cls, CallbackBreak<Field> callback) { doWithFields(cls, callback, null); } /** * @param cls * @param callback * @param superClass */ public static void doWithFields(Class cls, CallbackBreak<Field> callback, Class superClass) { try { while (cls != null && cls != Object.class && cls != superClass) { for (Field field : cls.getFields()) { callback.doWith(field); } cls = cls.getSuperclass(); } } catch (BreakException e) { } } /** * @param cls * @param callback */ public static void doWithDeclaredFields(Class cls, CallbackBreak<Field> callback) { doWithDeclaredFields(cls, callback, null); } /** * @param cls * @param callback * @param superClass */ public static void doWithDeclaredFields(Class cls, CallbackBreak<Field> callback, Class superClass) { try { while (cls != null && cls != Object.class && cls != superClass) { for (Field field : cls.getDeclaredFields()) { callback.doWith(field); } cls = cls.getSuperclass(); } } catch (BreakException e) { } } /** * @param cls * @param callback */ public static void doWithMethods(Class cls, CallbackBreak<Method> callback) { doWithMethods(cls, callback, null); } /** * @param cls * @param callback * @param superClass */ public static void doWithMethods(Class cls, CallbackBreak<Method> callback, Class superClass) { try { while (cls != null && cls != Object.class && cls != superClass) { for (Method method : cls.getMethods()) { callback.doWith(method); } cls = cls.getSuperclass(); } } catch (BreakException e) { } } /** * @param cls * @param callback */ public static void doWithDeclaredMethods(Class cls, CallbackBreak<Method> callback) { doWithDeclaredMethods(cls, callback, null); } /** * @param cls * @param callback * @param superClass */ public static void doWithDeclaredMethods(Class cls, CallbackBreak<Method> callback, Class superClass) { try { while (cls != null && cls != Object.class && cls != superClass) { for (Method method : cls.getDeclaredMethods()) { callback.doWith(method); } cls = cls.getSuperclass(); } } catch (BreakException e) { } } }