一、前言
关于keycloak的keycloak-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@ if (type1 instanceof TypeVariable<?>) {@b@ TypeVariable<?> typeVariable = (TypeVariable<?>) type1;@b@ if (isTypeBounded(type2, EMPTY_TYPES, typeVariable.getBounds())) {@b@ return true;@b@ }@b@ }@b@ if (type2 instanceof TypeVariable<?>) {@b@ TypeVariable<?> typeVariable = (TypeVariable<?>) type2;@b@ if (isTypeBounded(type1, typeVariable.getBounds(), EMPTY_TYPES)) {@b@ return true;@b@ }@b@ }@b@ return false;@b@ }@b@@b@ public static boolean matches(Type type1, Type type2) {@b@ if (type1 instanceof Class<?>) {@b@ Class<?> clazz = (Class<?>) type1;@b@ if (matches(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 (matches((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@ if (type1 instanceof TypeVariable<?>) {@b@ TypeVariable<?> typeVariable = (TypeVariable<?>) type1;@b@ if (isTypeBounded(type2, EMPTY_TYPES, typeVariable.getBounds())) {@b@ return true;@b@ }@b@ }@b@ if (type2 instanceof TypeVariable<?>) {@b@ TypeVariable<?> typeVariable = (TypeVariable<?>) type2;@b@ if (isTypeBounded(type1, typeVariable.getBounds(), EMPTY_TYPES)) {@b@ return true;@b@ }@b@ }@b@ return false;@b@ }@b@@b@ public static boolean isTypeBounded(Type type, Type[] lowerBounds, Type[] upperBounds) {@b@ if (lowerBounds.length > 0) {@b@ if (!isAssignableFrom(type, lowerBounds)) {@b@ return false;@b@ }@b@ }@b@ if (upperBounds.length > 0) {@b@ if (!isAssignableFrom(upperBounds, type)) {@b@ return false;@b@ }@b@ }@b@ return true;@b@ }@b@@b@ public static boolean isAssignableFrom(Class<?> rawType1, Type[] actualTypeArguments1, Type type2) {@b@ if (type2 instanceof ParameterizedType) {@b@ ParameterizedType parameterizedType = (ParameterizedType) type2;@b@ if (parameterizedType.getRawType() instanceof Class<?>) {@b@ if (isAssignableFrom(rawType1, actualTypeArguments1, (Class<?>) parameterizedType.getRawType(),@b@ parameterizedType.getActualTypeArguments())) {@b@ return true;@b@ }@b@ }@b@ } else if (type2 instanceof Class<?>) {@b@ Class<?> clazz = (Class<?>) type2;@b@ if (isAssignableFrom(rawType1, actualTypeArguments1, clazz, EMPTY_TYPES)) {@b@ return true;@b@ }@b@ } else if (type2 instanceof TypeVariable<?>) {@b@ TypeVariable<?> typeVariable = (TypeVariable<?>) type2;@b@ if (isTypeBounded(rawType1, actualTypeArguments1, typeVariable.getBounds())) {@b@ return true;@b@ }@b@ }@b@ return false;@b@ }@b@@b@ public static boolean matches(Class<?> rawType1, Type[] actualTypeArguments1, Type type2) {@b@ if (type2 instanceof ParameterizedType) {@b@ ParameterizedType parameterizedType = (ParameterizedType) type2;@b@ if (parameterizedType.getRawType() instanceof Class<?>) {@b@ if (matches(rawType1, actualTypeArguments1, (Class<?>) parameterizedType.getRawType(),@b@ parameterizedType.getActualTypeArguments())) {@b@ return true;@b@ }@b@ }@b@ } else if (type2 instanceof Class<?>) {@b@ Class<?> clazz = (Class<?>) type2;@b@ if (matches(rawType1, actualTypeArguments1, clazz, EMPTY_TYPES)) {@b@ return true;@b@ }@b@ }@b@ return false;@b@ }@b@@b@ /**@b@ * Check the assiginability of a set of <b>flattened</b> types. This algorithm will check whether any of the types1@b@ * matches a type in types2@b@ *@b@ * @param types1@b@ * @param types2@b@ *@b@ * @return@b@ */@b@ public static boolean isAssignableFrom(Set<Type> types1, Set<Type> types2) {@b@ for (Type type : types1) {@b@ if (isAssignableFrom(type, types2)) {@b@ return true;@b@ }@b@ }@b@ return false;@b@ }@b@@b@ /**@b@ * Check whether whether any of the types1 matches a type in types2@b@ *@b@ * @param types1@b@ * @param types2@b@ *@b@ * @return@b@ */@b@ public static boolean matches(Set<Type> types1, Set<Type> types2) {@b@ for (Type type : types1) {@b@ if (matches(type, types2)) {@b@ return true;@b@ }@b@ }@b@ return false;@b@ }@b@@b@ /**@b@ * Check the assignability of a set of <b>flattened</b> types. This algorithm will check whether any of the types1@b@ * matches a type in types2@b@ *@b@ * @param types1@b@ * @param type2@b@ *@b@ * @return@b@ */@b@ public static boolean isAssignableFrom(Set<Type> types1, Type type2) {@b@ for (Type type : types1) {@b@ if (isAssignableFrom(type, type2)) {@b@ return true;@b@ }@b@ }@b@ return false;@b@ }@b@@b@ public static boolean isAssignableFrom(Type[] types1, Type type2) {@b@ for (Type type : types1) {@b@ if (isAssignableFrom(type, type2)) {@b@ return true;@b@ }@b@ }@b@ return false;@b@ }@b@@b@ public static boolean isPrimitive(Type type) {@b@ Class<?> rawType = getRawType(type);@b@ return rawType == null ? false : rawType.isPrimitive();@b@ }@b@@b@ /**@b@ * <p>Creates a new instance of a class.</p>@b@ *@b@ * <p>This method will use the same class loader of the given class to create the new instance.</p>@b@ *@b@ * @param fromClass The class from where the instance should be created.@b@ *@b@ * @return A newly allocated instance of the class.@b@ *@b@ * @throws ClassNotFoundException@b@ * @throws IllegalAccessException@b@ * @throws InstantiationException@b@ */@b@ public static <T> T newInstance(final Class<T> fromClass) throws ClassNotFoundException, IllegalAccessException, InstantiationException {@b@ return newInstance(fromClass, fromClass.getName());@b@ }@b@@b@ /**@b@ * <p>Creates a new instance of a class given its <code>fullQualifiedName</code>.</p>@b@ *@b@ * <p>This method will use the same class loader of <code>type</code> to create the new instance.</p>@b@ *@b@ * @param type The class that will be used to get the class loader from.@b@ * @param fullQualifiedName The full qualified name of the class from which the instance will be created.@b@ *@b@ * @return A newly allocated instance of the class.@b@ *@b@ * @throws ClassNotFoundException@b@ * @throws IllegalAccessException@b@ * @throws InstantiationException@b@ */@b@ public static <T> T newInstance(final Class<?> type, final String fullQualifiedName) throws ClassNotFoundException, IllegalAccessException, InstantiationException {@b@ return (T) classForName(fullQualifiedName, type.getClassLoader()).newInstance();@b@ }@b@}