首页  |  知识库  |  资源下载  |  在线工具  |  A-Z  •  JAR  •  名词查         

关于keycloak源码包中Reflections类反射处理器获取注解、属性及声明方法

标签:keycloak,reflections,类反射处理器     发布时间:2018-05-13   

一、前言

关于keycloakkeycloak-common源码包org.keycloak.common.util.reflections.Reflections类映射器,将对象cast转为大写、获取声明方法getAllDeclaredFields、查找声明方法findDeclaredField、判断类是否存在某方法methodExists、获取类容器findDeclaredConstructor、获取所有容器getAllDeclaredConstructors集合、类方法调用invokeMethod重写、获取方法属性名getPropertyName、判断类是否可继承isFinal、实例化类的方法newInstance等。

二、源码说明

package org.keycloak.common.util.reflections;@b@@b@import java.beans.Introspector;@b@import java.io.Serializable;@b@import java.lang.annotation.Annotation;@b@import java.lang.reflect.AccessibleObject;@b@import java.lang.reflect.Constructor;@b@import java.lang.reflect.Field;@b@import java.lang.reflect.InvocationTargetException;@b@import java.lang.reflect.Member;@b@import java.lang.reflect.Method;@b@import java.lang.reflect.Modifier;@b@import java.lang.reflect.ParameterizedType;@b@import java.lang.reflect.Type;@b@import java.lang.reflect.TypeVariable;@b@import java.lang.reflect.WildcardType;@b@import java.security.AccessController;@b@import java.util.Arrays;@b@import java.util.HashMap;@b@import java.util.HashSet;@b@import java.util.Map;@b@import java.util.Set;@b@@b@ @b@public class Reflections {@b@    /**@b@     * An empty array of type {@link java.lang.annotation.Annotation}, useful converting lists to arrays.@b@     */@b@    public static final Annotation[] EMPTY_ANNOTATION_ARRAY = new Annotation[0];@b@@b@    /**@b@     * An empty array of type {@link Object}, useful for converting lists to arrays.@b@     */@b@    public static final Object[] EMPTY_OBJECT_ARRAY = new Object[0];@b@@b@    public static final Type[] EMPTY_TYPES = {};@b@@b@    public static final Class<?>[] EMPTY_CLASSES = new Class<?>[0];@b@@b@    private Reflections() {@b@    }@b@@b@    /**@b@     * <p> Perform a runtime cast. Similar to {@link Class#cast(Object)}, but useful when you do not have a {@link@b@     * Class} object for type you wish to cast to. </p> <p/> <p> {@link Class#cast(Object)} should be used if possible@b@     * </p>@b@     *@b@     * @param <T> the type to cast to@b@     * @param obj the object to perform the cast on@b@     *@b@     * @return the casted object@b@     *@b@     * @throws ClassCastException if the type T is not a subtype of the object@b@     * @see Class#cast(Object)@b@     */@b@    @SuppressWarnings("unchecked")@b@    public static <T> T cast(Object obj) {@b@        return (T) obj;@b@    }@b@@b@    /**@b@     * Get all the declared fields on the class hierarchy. This <b>will</b> return overridden fields.@b@     *@b@     * @param clazz The class to search@b@     *@b@     * @return the set of all declared fields or an empty set if there are none@b@     */@b@    public static Set<Field> getAllDeclaredFields(Class<?> clazz) {@b@        HashSet<Field> fields = new HashSet<Field>();@b@        for (Class<?> c = clazz; c != null && c != Object.class; c = c.getSuperclass()) {@b@            for (Field a : c.getDeclaredFields()) {@b@                fields.add(a);@b@            }@b@        }@b@        return fields;@b@    }@b@@b@    /**@b@     * Search the class hierarchy for a field with the given name. Will return the nearest match, starting with the@b@     * class specified and searching up the hierarchy.@b@     *@b@     * @param clazz The class to search@b@     * @param name The name of the field to search for@b@     *@b@     * @return The field found, or null if no field is found@b@     */@b@    public static Field findDeclaredField(Class<?> clazz, String name) {@b@        for (Class<?> c = clazz; c != null && c != Object.class; c = c.getSuperclass()) {@b@            try {@b@                return c.getDeclaredField(name);@b@            } catch (NoSuchFieldException e) {@b@                // No-op, we continue looking up the class hierarchy@b@            }@b@        }@b@        return null;@b@    }@b@@b@    /**@b@     * Search for annotations with the specified meta annotation type@b@     *@b@     * @param annotations The annotation set to search@b@     * @param metaAnnotationType The type of the meta annotation to search for@b@     *@b@     * @return The set of annotations with the specified meta annotation, or an empty set if none are found@b@     */@b@    public static Set<Annotation> getAnnotationsWithMetaAnnotation(@b@            Set<Annotation> annotations, Class<? extends Annotation> metaAnnotationType) {@b@        Set<Annotation> set = new HashSet<Annotation>();@b@        for (Annotation annotation : annotations) {@b@            if (annotation.annotationType().isAnnotationPresent(metaAnnotationType)) {@b@                set.add(annotation);@b@            }@b@        }@b@        return set;@b@    }@b@@b@    /**@b@     * Determine if a method exists in a specified class hierarchy@b@     *@b@     * @param clazz The class to search@b@     * @param name The name of the method@b@     *@b@     * @return true if a method is found, otherwise false@b@     */@b@    public static boolean methodExists(Class<?> clazz, String name) {@b@        for (Class<?> c = clazz; c != null && c != Object.class; c = c.getSuperclass()) {@b@            for (Method m : c.getDeclaredMethods()) {@b@                if (m.getName().equals(name)) {@b@                    return true;@b@                }@b@            }@b@        }@b@        return false;@b@    }@b@@b@    /**@b@     * Get all the declared methods on the class hierarchy. This <b>will</b> return overridden methods.@b@     *@b@     * @param clazz The class to search@b@     *@b@     * @return the set of all declared methods or an empty set if there are none@b@     */@b@    public static Set<Method> getAllDeclaredMethods(Class<?> clazz) {@b@        HashSet<Method> methods = new HashSet<Method>();@b@        for (Class<?> c = clazz; c != null && c != Object.class; c = c.getSuperclass()) {@b@            for (Method a : c.getDeclaredMethods()) {@b@                methods.add(a);@b@            }@b@        }@b@        return methods;@b@    }@b@@b@    /**@b@     * Search the class hierarchy for a method with the given name and arguments. Will return the nearest match,@b@     * starting with the class specified and searching up the hierarchy.@b@     *@b@     * @param clazz The class to search@b@     * @param name The name of the method to search for@b@     * @param args The arguments of the method to search for@b@     *@b@     * @return The method found, or null if no method is found@b@     */@b@    public static Method findDeclaredMethod(Class<?> clazz, String name, Class<?>... args) {@b@        for (Class<?> c = clazz; c != null && c != Object.class; c = c.getSuperclass()) {@b@            try {@b@                return c.getDeclaredMethod(name, args);@b@            } catch (NoSuchMethodException e) {@b@                // No-op, continue the search@b@            }@b@        }@b@        return null;@b@    }@b@@b@    /**@b@     * Search the class hierarchy for a constructor with the given arguments. Will return the nearest match, starting@b@     * with the class specified and searching up the hierarchy.@b@     *@b@     * @param clazz The class to search@b@     * @param args The arguments of the constructor to search for@b@     *@b@     * @return The constructor found, or null if no constructor is found@b@     */@b@    public static Constructor<?> findDeclaredConstructor(Class<?> clazz, Class<?>... args) {@b@        for (Class<?> c = clazz; c != null && c != Object.class; c = c.getSuperclass()) {@b@            try {@b@                return c.getDeclaredConstructor(args);@b@            } catch (NoSuchMethodException e) {@b@                // No-op, continue the search@b@            }@b@        }@b@        return null;@b@    }@b@@b@    /**@b@     * Get all the declared constructors on the class hierarchy. This <b>will</b> return overridden constructors.@b@     *@b@     * @param clazz The class to search@b@     *@b@     * @return the set of all declared constructors or an empty set if there are none@b@     */@b@    public static Set<Constructor<?>> getAllDeclaredConstructors(Class<?> clazz) {@b@        HashSet<Constructor<?>> constructors = new HashSet<Constructor<?>>();@b@        for (Class<?> c = clazz; c != null && c != Object.class; c = c.getSuperclass()) {@b@            for (Constructor<?> constructor : c.getDeclaredConstructors()) {@b@                constructors.add(constructor);@b@            }@b@        }@b@        return constructors;@b@    }@b@@b@    /**@b@     * Get the type of the member@b@     *@b@     * @param member The member@b@     *@b@     * @return The type of the member@b@     *@b@     * @throws UnsupportedOperationException if the member is not a field, method, or constructor@b@     */@b@    public static Class<?> getMemberType(Member member) {@b@        if (member instanceof Field) {@b@            return ((Field) member).getType();@b@        } else if (member instanceof Method) {@b@            return ((Method) member).getReturnType();@b@        } else if (member instanceof Constructor<?>) {@b@            return ((Constructor<?>) member).getDeclaringClass();@b@        } else {@b@            throw new UnsupportedOperationException("Cannot operate on a member of type " + member.getClass());@b@        }@b@    }@b@@b@    /**@b@     * <p> Loads and initializes a class for the given name. </p> <p/> <p> If the Thread Context Class Loader is@b@     * available, it will be used, otherwise the classloader used to load {@link Reflections} will be used </p> <p/> <p>@b@     * It is also possible to specify additional classloaders to attempt to load the class with. If the first attempt@b@     * fails, then these additional loaders are tried in order. </p>@b@     *@b@     * @param name the name of the class to load@b@     * @param loaders additional classloaders to use to attempt to load the class@b@     *@b@     * @return the class object@b@     *@b@     * @throws ClassNotFoundException if the class cannot be found@b@     */@b@    public static <T> Class<T> classForName(String name, ClassLoader... loaders) throws ClassNotFoundException {@b@        try {@b@            if (Thread.currentThread().getContextClassLoader() != null) {@b@                return (Class<T>) Class.forName(name, true, Thread.currentThread().getContextClassLoader());@b@            } else {@b@                return (Class<T>) Class.forName(name);@b@            }@b@        } catch (ClassNotFoundException e) {@b@            for (ClassLoader l : loaders) {@b@                try {@b@                    return (Class<T>) Class.forName(name, true, l);@b@                } catch (ClassNotFoundException ex) {@b@@b@                }@b@            }@b@        }@b@        if (Thread.currentThread().getContextClassLoader() != null) {@b@            throw new ClassNotFoundException("Could not load class " + name +@b@                    " with the context class loader " + Thread.currentThread().getContextClassLoader().toString() +@b@                    " or any of the additional ClassLoaders: " + Arrays.toString(loaders));@b@        } else {@b@            throw new ClassNotFoundException("Could not load class " + name +@b@                    " using Class.forName or using any of the additional ClassLoaders: " +@b@                    Arrays.toString(loaders));@b@        }@b@    }@b@@b@    private static String buildInvokeMethodErrorMessage(Method method, Object obj, Object... args) {@b@        StringBuilder message = new StringBuilder(@b@                String.format("Exception invoking method [%s] on object [%s], using arguments [",@b@                        method.getName(), obj));@b@        if (args != null) {@b@            for (int i = 0; i < args.length; i++) {@b@                message.append((i > 0 ? "," : "") + args[i]);@b@            }@b@        }@b@        message.append("]");@b@        return message.toString();@b@    }@b@@b@    /**@b@     * <p> Invoke the specified method on the provided instance, passing any additional arguments included in this@b@     * method as arguments to the specified method. </p> <p/> <p>This method provides the same functionality and throws@b@     * the same exceptions as {@link Reflections#invokeMethod(boolean, Method, Class, Object, Object...)}, with the@b@     * expected return type set to {@link Object} and no change to the method's accessibility.</p>@b@     *@b@     * @see Reflections#invokeMethod(boolean, Method, Class, Object, Object...)@b@     * @see Method#invoke(Object, Object...)@b@     */@b@    public static Object invokeMethod(Method method, Object instance, Object... args) {@b@        return invokeMethod(false, method, Object.class, instance, args);@b@    }@b@@b@    /**@b@     * <p> Invoke the specified method on the provided instance, passing any additional arguments included in this@b@     * method as arguments to the specified method. </p> <p/> <p> This method attempts to set the accessible flag of the@b@     * method in a {link PrivilegedAction} before invoking the method if the first argument is true. </p> <p/> <p>This@b@     * method provides the same functionality and throws the same exceptions as {@link Reflections#invokeMethod(boolean,@b@     * Method, Class, Object, Object...)}, with the expected return type set to {@link Object}.</p>@b@     *@b@     * @see Reflections#invokeMethod(boolean, Method, Class, Object, Object...)@b@     * @see Method#invoke(Object, Object...)@b@     */@b@    public static Object invokeMethod(boolean setAccessible, Method method, Object instance, Object... args) {@b@        return invokeMethod(setAccessible, method, Object.class, instance, args);@b@    }@b@@b@    /**@b@     * <p> Invoke the specified method on the provided instance, passing any additional arguments included in this@b@     * method as arguments to the specified method. </p> <p/> <p>This method provides the same functionality and throws@b@     * the same exceptions as {@link Reflections#invokeMethod(boolean, Method, Class, Object, Object...)}, with the@b@     * expected return type set to {@link Object} and honoring the accessibility of the method.</p>@b@     *@b@     * @see Reflections#invokeMethod(boolean, Method, Class, Object, Object...)@b@     * @see Method#invoke(Object, Object...)@b@     */@b@    public static <T> T invokeMethod(Method method, Class<T> expectedReturnType, Object instance, Object... args) {@b@        return invokeMethod(false, method, expectedReturnType, instance, args);@b@    }@b@@b@    /**@b@     * <p> Invoke the method on the instance, with any arguments specified, casting the result of invoking the method to@b@     * the expected return type. </p> <p/> <p> This method wraps {@link Method#invoke(Object, Object...)}, converting@b@     * the checked exceptions that {@link Method#invoke(Object, Object...)} specifies to runtime exceptions. </p> <p/>@b@     * <p> If instructed, this method attempts to set the accessible flag of the method in a {link PrivilegedAction}@b@     * before invoking the method. </p>@b@     *@b@     * @param setAccessible flag indicating whether method should first be set as accessible@b@     * @param method the method to invoke@b@     * @param instance the instance to invoke the method@b@     * @param args the arguments to the method@b@     *@b@     * @return the result of invoking the method, or null if the method's return type is void@b@     *@b@     * @throws RuntimeException if this <code>Method</code> object enforces Java language access control and the@b@     * underlying method is inaccessible or if the underlying method throws an exception or if the initialization@b@     * provoked by this method fails.@b@     * @throws IllegalArgumentException if the method is an instance method and the specified <code>instance</code>@b@     * argument is not an instance of the class or interface declaring the underlying method (or of a subclass or@b@     * implementor thereof); if the number of actual and formal parameters differ; if an unwrapping conversion for@b@     * primitive arguments fails; or if, after possible unwrapping, a parameter value cannot be converted to the@b@     * corresponding formal parameter type by a method invocation conversion.@b@     * @throws NullPointerException if the specified <code>instance</code> is null and the method is an instance@b@     * method.@b@     * @throws ClassCastException if the result of invoking the method cannot be cast to the expectedReturnType@b@     * @throws ExceptionInInitializerError if the initialization provoked by this method fails.@b@     * @see Method#invoke(Object, Object...)@b@     */@b@    public static <T> T invokeMethod(boolean setAccessible, Method method,@b@                                     Class<T> expectedReturnType, Object instance, Object... args) {@b@        if (setAccessible && !method.isAccessible()) {@b@            setAccessible(method);@b@        }@b@@b@        try {@b@            return expectedReturnType.cast(method.invoke(instance, args));@b@        } catch (IllegalAccessException ex) {@b@            throw new RuntimeException(buildInvokeMethodErrorMessage(method, instance, args), ex);@b@        } catch (IllegalArgumentException ex) {@b@            throw new IllegalArgumentException(buildInvokeMethodErrorMessage(method, instance, args), ex);@b@        } catch (InvocationTargetException ex) {@b@            throw new RuntimeException(buildInvokeMethodErrorMessage(method, instance, args), ex.getCause());@b@        } catch (NullPointerException ex) {@b@            NullPointerException ex2 = new NullPointerException(buildInvokeMethodErrorMessage(method, instance, args));@b@            ex2.initCause(ex.getCause());@b@            throw ex2;@b@        } catch (ExceptionInInitializerError e) {@b@            ExceptionInInitializerError e2 = new ExceptionInInitializerError(@b@                    buildInvokeMethodErrorMessage(method, instance, args));@b@            e2.initCause(e.getCause());@b@            throw e2;@b@        }@b@    }@b@@b@    /**@b@     * Set the accessibility flag on the {@link AccessibleObject} as described in {@link@b@     * AccessibleObject#setAccessible(boolean)} within the context of a {link PrivilegedAction}.@b@     *@b@     * @param <A> member the accessible object type@b@     * @param member the accessible object@b@     *@b@     * @return the accessible object after the accessible flag has been altered@b@     */@b@    public static <A extends AccessibleObject> A setAccessible(A member) {@b@        AccessController.doPrivileged(new SetAccessiblePrivilegedAction(member));@b@        return member;@b@    }@b@@b@    private static String buildSetFieldValueErrorMessage(Field field, Object obj, Object value) {@b@        return String.format("Exception setting [%s] field on object [%s] to value [%s]", field.getName(), obj, value);@b@    }@b@@b@    private static String buildGetFieldValueErrorMessage(Field field, Object obj) {@b@        return String.format("Exception reading [%s] field from object [%s].", field.getName(), obj);@b@    }@b@@b@    public static Object getFieldValue(Field field, Object instance) {@b@        return getFieldValue(field, instance, Object.class);@b@    }@b@@b@    /**@b@     * <p> Get the value of the field, on the specified instance, casting the value of the field to the expected type.@b@     * </p> <p/> <p> This method wraps {@link Field#get(Object)}, converting the checked exceptions that {@link@b@     * Field#get(Object)} specifies to runtime exceptions. </p>@b@     *@b@     * @param <T> the type of the field's value@b@     * @param field the field to operate on@b@     * @param instance the instance from which to retrieve the value@b@     * @param expectedType the expected type of the field's value@b@     *@b@     * @return the value of the field@b@     *@b@     * @throws RuntimeException if the underlying field is inaccessible.@b@     * @throws IllegalArgumentException if the specified <code>instance</code> is not an instance of the class or@b@     * interface declaring the underlying field (or a subclass or implementor thereof).@b@     * @throws NullPointerException if the specified <code>instance</code> is null and the field is an instance field.@b@     * @throws ExceptionInInitializerError if the initialization provoked by this method fails.@b@     */@b@    public static <T> T getFieldValue(Field field, Object instance, Class<T> expectedType) {@b@        try {@b@            return Reflections.cast(field.get(instance));@b@        } catch (IllegalAccessException e) {@b@            throw new RuntimeException(buildGetFieldValueErrorMessage(field, instance), e);@b@        } catch (NullPointerException ex) {@b@            NullPointerException ex2 = new NullPointerException(buildGetFieldValueErrorMessage(field, instance));@b@            ex2.initCause(ex.getCause());@b@            throw ex2;@b@        } catch (ExceptionInInitializerError e) {@b@            ExceptionInInitializerError e2 = new ExceptionInInitializerError(@b@                    buildGetFieldValueErrorMessage(field, instance));@b@            e2.initCause(e.getCause());@b@            throw e2;@b@        }@b@    }@b@@b@    /**@b@     * Extract the raw type, given a type.@b@     *@b@     * @param <T> the type@b@     * @param type the type to extract the raw type from@b@     *@b@     * @return the raw type, or null if the raw type cannot be determined.@b@     */@b@    @SuppressWarnings("unchecked")@b@    public static <T> Class<T> getRawType(Type type) {@b@        if (type instanceof Class<?>) {@b@            return (Class<T>) type;@b@        } else if (type instanceof ParameterizedType) {@b@            if (((ParameterizedType) type).getRawType() instanceof Class<?>) {@b@                return (Class<T>) ((ParameterizedType) type).getRawType();@b@            }@b@        }@b@        return null;@b@    }@b@@b@    /**@b@     * Check if a class is serializable.@b@     *@b@     * @param clazz The class to check@b@     *@b@     * @return true if the class implements serializable or is a primitive@b@     */@b@    public static boolean isSerializable(Class<?> clazz) {@b@        return clazz.isPrimitive() || Serializable.class.isAssignableFrom(clazz);@b@    }@b@@b@@b@    public static Map<Class<?>, Type> buildTypeMap(Set<Type> types) {@b@        Map<Class<?>, Type> map = new HashMap<Class<?>, Type>();@b@        for (Type type : types) {@b@            if (type instanceof Class<?>) {@b@                map.put((Class<?>) type, type);@b@            } else if (type instanceof ParameterizedType) {@b@                if (((ParameterizedType) type).getRawType() instanceof Class<?>) {@b@                    map.put((Class<?>) ((ParameterizedType) type).getRawType(), type);@b@                }@b@            } else if (type instanceof TypeVariable<?>) {@b@@b@            }@b@        }@b@        return map;@b@    }@b@@b@    public static boolean isCacheable(Set<Annotation> annotations) {@b@        for (Annotation qualifier : annotations) {@b@            Class<?> clazz = qualifier.getClass();@b@            if (clazz.isAnonymousClass() || (clazz.isMemberClass() && isStatic(clazz))) {@b@                return false;@b@            }@b@        }@b@        return true;@b@    }@b@@b@    public static boolean isCacheable(Annotation[] annotations) {@b@        for (Annotation qualifier : annotations) {@b@            Class<?> clazz = qualifier.getClass();@b@            if (clazz.isAnonymousClass() || (clazz.isMemberClass() && isStatic(clazz))) {@b@                return false;@b@            }@b@        }@b@        return true;@b@    }@b@@b@    /**@b@     * Gets the property name from a getter method.@b@     * <p/>@b@     * We extend JavaBean conventions, allowing the getter method to have parameters@b@     *@b@     * @param method The getter method@b@     *@b@     * @return The name of the property. Returns null if method wasn't JavaBean getter-styled@b@     */@b@    public static String getPropertyName(Method method) {@b@        String methodName = method.getName();@b@        if (methodName.matches("^(get).*")) {@b@            return Introspector.decapitalize(methodName.substring(3));@b@        } else if (methodName.matches("^(is).*")) {@b@            return Introspector.decapitalize(methodName.substring(2));@b@        } else {@b@            return null;@b@        }@b@@b@    }@b@@b@    /**@b@     * Checks if class is final@b@     *@b@     * @param clazz The class to check@b@     *@b@     * @return True if final, false otherwise@b@     */@b@    public static boolean isFinal(Class<?> clazz) {@b@        return Modifier.isFinal(clazz.getModifiers());@b@    }@b@@b@    public static int getNesting(Class<?> clazz) {@b@        if (clazz.isMemberClass() && !isStatic(clazz)) {@b@            return 1 + getNesting(clazz.getDeclaringClass());@b@        } else {@b@            return 0;@b@        }@b@    }@b@@b@    /**@b@     * Checks if member is final@b@     *@b@     * @param member The member to check@b@     *@b@     * @return True if final, false otherwise@b@     */@b@    public static boolean isFinal(Member member) {@b@        return Modifier.isFinal(member.getModifiers());@b@    }@b@@b@    /**@b@     * Checks if member is private@b@     *@b@     * @param member The member to check@b@     *@b@     * @return True if final, false otherwise@b@     */@b@    public static boolean isPrivate(Member member) {@b@        return Modifier.isPrivate(member.getModifiers());@b@    }@b@@b@    /**@b@     * Checks if type or member is final@b@     *@b@     * @param type Type or member@b@     *@b@     * @return True if final, false otherwise@b@     */@b@    public static boolean isTypeOrAnyMethodFinal(Class<?> type) {@b@        return getNonPrivateFinalMethodOrType(type) != null;@b@    }@b@@b@    public static Object getNonPrivateFinalMethodOrType(Class<?> type) {@b@        if (isFinal(type)) {@b@            return type;@b@        }@b@        for (Method method : type.getDeclaredMethods()) {@b@            if (isFinal(method) && !isPrivate(method)) {@b@                return method;@b@            }@b@        }@b@        return null;@b@    }@b@@b@    public static boolean isPackagePrivate(int mod) {@b@        return !(Modifier.isPrivate(mod) || Modifier.isProtected(mod) || Modifier.isPublic(mod));@b@    }@b@@b@    /**@b@     * Checks if type is static@b@     *@b@     * @param type Type to check@b@     *@b@     * @return True if static, false otherwise@b@     */@b@    public static boolean isStatic(Class<?> type) {@b@        return Modifier.isStatic(type.getModifiers());@b@    }@b@@b@    /**@b@     * Checks if member is static@b@     *@b@     * @param member Member to check@b@     *@b@     * @return True if static, false otherwise@b@     */@b@    public static boolean isStatic(Member member) {@b@        return Modifier.isStatic(member.getModifiers());@b@    }@b@@b@    public static boolean isTransient(Member member) {@b@        return Modifier.isTransient(member.getModifiers());@b@    }@b@@b@    /**@b@     * Checks if a method is abstract@b@     *@b@     * @param method@b@     *@b@     * @return@b@     */@b@    public static boolean isAbstract(Method method) {@b@        return Modifier.isAbstract(method.getModifiers());@b@    }@b@@b@    /**@b@     * Checks if raw type is array type@b@     *@b@     * @param rawType The raw type to check@b@     *@b@     * @return True if array, false otherwise@b@     */@b@    public static boolean isArrayType(Class<?> rawType) {@b@        return rawType.isArray();@b@    }@b@@b@    /**@b@     * Checks if type is parameterized type@b@     *@b@     * @param type The type to check@b@     *@b@     * @return True if parameterized, false otherwise@b@     */@b@    public static boolean isParameterizedType(Class<?> type) {@b@        return type.getTypeParameters().length > 0;@b@    }@b@@b@    public static boolean isParamerterizedTypeWithWildcard(Class<?> type) {@b@        if (isParameterizedType(type)) {@b@            return containsWildcards(type.getTypeParameters());@b@        } else {@b@            return false;@b@        }@b@    }@b@@b@    public static boolean containsWildcards(Type[] types) {@b@        for (Type type : types) {@b@            if (type instanceof WildcardType) {@b@                return true;@b@            }@b@        }@b@        return false;@b@    }@b@@b@    /**@b@     * Check the assignability of one type to another, taking into account the actual type arguements@b@     *@b@     * @param rawType1 the raw type of the class to check@b@     * @param actualTypeArguments1 the actual type arguements to check, or an empty array if not a parameterized type@b@     * @param rawType2 the raw type of the class to check@b@     * @param actualTypeArguments2 the actual type arguements to check, or an empty array if not a parameterized type@b@     *@b@     * @return@b@     */@b@    public static boolean isAssignableFrom(Class<?> rawType1, Type[] actualTypeArguments1,@b@                                           Class<?> rawType2, Type[] actualTypeArguments2) {@b@        return Types.boxedClass(rawType1).isAssignableFrom(Types.boxedClass(rawType2)) &&@b@                isAssignableFrom(actualTypeArguments1, actualTypeArguments2);@b@    }@b@@b@    public static boolean matches(Class<?> rawType1, Type[] actualTypeArguments1,@b@                                  Class<?> rawType2, Type[] actualTypeArguments2) {@b@        return Types.boxedClass(rawType1).equals(Types.boxedClass(rawType2)) &&@b@                isAssignableFrom(actualTypeArguments1, actualTypeArguments2);@b@    }@b@@b@    public static boolean isAssignableFrom(Type[] actualTypeArguments1, Type[] actualTypeArguments2) {@b@        for (int i = 0; i < actualTypeArguments1.length; i++) {@b@            Type type1 = actualTypeArguments1[i];@b@            Type type2 = Object.class;@b@            if (actualTypeArguments2.length > i) {@b@                type2 = actualTypeArguments2[i];@b@            }@b@            if (!isAssignableFrom(type1, type2)) {@b@                return false;@b@            }@b@        }@b@        return true;@b@    }@b@@b@    public static boolean isAssignableFrom(Type type1, Set<? extends Type> types2) {@b@        for (Type type2 : types2) {@b@            if (isAssignableFrom(type1, type2)) {@b@                return true;@b@            }@b@        }@b@        return false;@b@    }@b@@b@    public static boolean matches(Type type1, Set<? extends Type> types2) {@b@        for (Type type2 : types2) {@b@            if (matches(type1, type2)) {@b@                return true;@b@            }@b@        }@b@        return false;@b@    }@b@@b@    public static boolean isAssignableFrom(Type type1, Type[] types2) {@b@        for (Type type2 : types2) {@b@            if (isAssignableFrom(type1, type2)) {@b@                return true;@b@            }@b@        }@b@        return false;@b@    }@b@@b@    public static boolean isAssignableFrom(Type type1, Type type2) {@b@        if (type1 instanceof Class<?>) {@b@            Class<?> clazz = (Class<?>) type1;@b@            if (isAssignableFrom(clazz, EMPTY_TYPES, type2)) {@b@                return true;@b@            }@b@        }@b@        if (type1 instanceof ParameterizedType) {@b@            ParameterizedType parameterizedType1 = (ParameterizedType) type1;@b@            if (parameterizedType1.getRawType() instanceof Class<?>) {@b@                if (isAssignableFrom((Class<?>) parameterizedType1.getRawType(),@b@                        parameterizedType1.getActualTypeArguments(), type2)) {@b@                    return true;@b@                }@b@            }@b@        }@b@        if (type1 instanceof WildcardType) {@b@            WildcardType wildcardType = (WildcardType) type1;@b@            if (isTypeBounded(type2, wildcardType.getLowerBounds(), wildcardType.getUpperBounds())) {@b@                return true;@b@            }@b@        }@b@        if (type2 instanceof WildcardType) {@b@            WildcardType wildcardType = (WildcardType) type2;@b@            if (isTypeBounded(type1, wildcardType.getUpperBounds(), wildcardType.getLowerBounds())) {@b@                return true;@b@            }@b@        }@b@ &nbs