/** * Find an accessible constructor with compatible parameters. Compatible parameters mean that * every method parameter is assignable from the given parameters. In other words, it finds * constructor that will take the parameters given. * * <p>First it checks if there is constructor matching the exact signature. If no such, all the * constructors of the class are tested if their signatures are assignment compatible with the * parameter types. The first matching constructor is returned. * * @param cls find constructor for this class * @param parameterTypes find method with compatible parameters * @return a valid Constructor object. If there's no matching constructor, returns <code>null * </code>. */ public static Constructor getMatchingAccessibleConstructor(Class cls, Class[] parameterTypes) { // see if we can find the constructor directly // most of the time this works and it's much faster try { Constructor ctor = cls.getConstructor(parameterTypes); MemberUtils.setAccessibleWorkaround(ctor); return ctor; } catch (NoSuchMethodException e) { /* SWALLOW */ } Constructor result = null; // search through all constructors Constructor[] ctors = cls.getConstructors(); for (int i = 0; i < ctors.length; i++) { // compare parameters if (ClassUtils.isAssignable(parameterTypes, ctors[i].getParameterTypes(), true)) { // get accessible version of method Constructor ctor = getAccessibleConstructor(ctors[i]); if (ctor != null) { MemberUtils.setAccessibleWorkaround(ctor); if (result == null || MemberUtils.compareParameterTypes( ctor.getParameterTypes(), result.getParameterTypes(), parameterTypes) < 0) { result = ctor; } } } } return result; }
/* 61: */ /* 62: */ public static Field getDeclaredField( Class cls, String fieldName, boolean forceAccess) /* 63: */ { /* 64:164 */ if (cls == null) { /* 65:165 */ throw new IllegalArgumentException("The class must not be null"); /* 66: */ } /* 67:167 */ if (fieldName == null) { /* 68:168 */ throw new IllegalArgumentException("The field name must not be null"); /* 69: */ } /* 70: */ try /* 71: */ { /* 72:172 */ Field field = cls.getDeclaredField(fieldName); /* 73:173 */ if (!MemberUtils.isAccessible(field)) { /* 74:174 */ if (forceAccess) { /* 75:175 */ field.setAccessible(true); /* 76: */ } else { /* 77:177 */ return null; /* 78: */ } /* 79: */ } /* 80:180 */ return field; /* 81: */ } /* 82: */ catch (NoSuchFieldException e) { } /* 83:183 */ return null; /* 84: */ }
/** * Write a field. * * @param field to write * @param target the object to call on, may be null for static fields * @param value to set * @param forceAccess whether to break scope restrictions using the <code>setAccessible</code> * method. <code>False</code> will only match public fields. * @throws IllegalArgumentException if the field is null * @throws IllegalAccessException if the field is not made accessible or is final */ public static void writeField(Field field, Object target, Object value, boolean forceAccess) throws IllegalAccessException { if (field == null) { throw new IllegalArgumentException("The field must not be null"); } if (forceAccess && !field.isAccessible()) { field.setAccessible(true); } else { MemberUtils.setAccessibleWorkaround(field); } field.set(target, value); }
/* 141: */ /* 142: */ public static Object readField(Field field, Object target, boolean forceAccess) /* 143: */ throws IllegalAccessException /* 144: */ { /* 145:308 */ if (field == null) { /* 146:309 */ throw new IllegalArgumentException("The field must not be null"); /* 147: */ } /* 148:311 */ if ((forceAccess) && (!field.isAccessible())) { /* 149:312 */ field.setAccessible(true); /* 150: */ } else { /* 151:314 */ MemberUtils.setAccessibleWorkaround(field); /* 152: */ } /* 153:316 */ return field.get(target); /* 154: */ }
/* 251: */ /* 252: */ public static void writeField( Field field, Object target, Object value, boolean forceAccess) /* 253: */ throws IllegalAccessException /* 254: */ { /* 255:515 */ if (field == null) { /* 256:516 */ throw new IllegalArgumentException("The field must not be null"); /* 257: */ } /* 258:518 */ if ((forceAccess) && (!field.isAccessible())) { /* 259:519 */ field.setAccessible(true); /* 260: */ } else { /* 261:521 */ MemberUtils.setAccessibleWorkaround(field); /* 262: */ } /* 263:523 */ field.set(target, value); /* 264: */ }
/** * Find an accessible method that matches the given name and has compatible parameters. Compatible * parameters mean that every method parameter is assignable from the given parameters. In other * words, it finds a method with the given name that will take the parameters given. * * <p> * * <p>This method is used by {@link #invokeMethod(Object object, String methodName, Object[] args, * Class[] parameterTypes)}. * * <p>This method can match primitive parameter by passing in wrapper classes. For example, a * <code>Boolean</code> will match a primitive <code>boolean</code> parameter. * * @param cls find method in this class * @param methodName find method with this name * @param parameterTypes find method with most compatible parameters * @return The accessible method */ public static Method getMatchingAccessibleMethod( Class cls, String methodName, Class[] parameterTypes) { try { Method method = cls.getMethod(methodName, parameterTypes); MemberUtils.setAccessibleWorkaround(method); return method; } catch (NoSuchMethodException e) { /* SWALLOW */ } // search through all methods Method bestMatch = null; Method[] methods = cls.getMethods(); for (int i = 0, size = methods.length; i < size; i++) { if (methods[i].getName().equals(methodName)) { // compare parameters if (ClassUtils.isAssignable(parameterTypes, methods[i].getParameterTypes(), true)) { // get accessible version of method Method accessibleMethod = getAccessibleMethod(methods[i]); if (accessibleMethod != null) { if (bestMatch == null || MemberUtils.compareParameterTypes( accessibleMethod.getParameterTypes(), bestMatch.getParameterTypes(), parameterTypes) < 0) { bestMatch = accessibleMethod; } } } } } if (bestMatch != null) { MemberUtils.setAccessibleWorkaround(bestMatch); } return bestMatch; }
/** * Return an accessible method (that is, one that can be invoked via reflection) that implements * the specified Method. If no such method can be found, return <code>null</code>. * * @param method The method that we wish to call * @return The accessible method */ public static Method getAccessibleMethod(Method method) { if (!MemberUtils.isAccessible(method)) { return null; } // If the declaring class is public, we are done Class cls = method.getDeclaringClass(); if (Modifier.isPublic(cls.getModifiers())) { return method; } String methodName = method.getName(); Class[] parameterTypes = method.getParameterTypes(); // Check the implemented interfaces and subinterfaces method = getAccessibleMethodFromInterfaceNest(cls, methodName, parameterTypes); // Check the superclass chain if (method == null) { method = getAccessibleMethodFromSuperclass(cls, methodName, parameterTypes); } return method; }
/** * Gets an accessible <code>Field</code> by name breaking scope if requested. Only the specified * class will be considered. * * @param cls the class to reflect, must not be null * @param fieldName the field name to obtain * @param forceAccess whether to break scope restrictions using the <code>setAccessible</code> * method. False will only match public fields. * @return the Field object * @throws IllegalArgumentException if the class or field name is null */ public static Field getDeclaredField(Class cls, String fieldName, boolean forceAccess) { if (cls == null) { throw new IllegalArgumentException("The class must not be null"); } if (fieldName == null) { throw new IllegalArgumentException("The field name must not be null"); } try { // only consider the specified class by using getDeclaredField() Field field = cls.getDeclaredField(fieldName); if (!MemberUtils.isAccessible(field)) { if (forceAccess) { field.setAccessible(true); } else { return null; } } return field; } catch (NoSuchFieldException e) { } return null; }
/* 11: */ public static Field getField(Class cls, String fieldName) /* 12: */ { /* 13: 60 */ Field field = getField(cls, fieldName, false); /* 14: 61 */ MemberUtils.setAccessibleWorkaround(field); /* 15: 62 */ return field; /* 16: */ }
/** * Gets an accessible <code>Field</code> by name respecting scope. Superclasses/interfaces will be * considered. * * @param cls the class to reflect, must not be null * @param fieldName the field name to obtain * @return the Field object * @throws IllegalArgumentException if the class or field name is null */ public static Field getField(Class cls, String fieldName) { Field field = getField(cls, fieldName, false); MemberUtils.setAccessibleWorkaround(field); return field; }
/** * Returns accessible version of the given constructor. * * @param ctor prototype constructor object. * @return <code>null</code> if accessible constructor can not be found. * @see java.lang.SecurityManager */ public static Constructor getAccessibleConstructor(Constructor ctor) { return MemberUtils.isAccessible(ctor) && Modifier.isPublic(ctor.getDeclaringClass().getModifiers()) ? ctor : null; }