/** * Gets the method with the given name and parameters from the given instance or class. If instanceOrClass is a class, then we get a * static method. * * @param instanceOrClass the instance or class to get the method of * @param methodName the name of the method * @param parameterTypes the parameter-types of the method to get * @return the method * @throws NoSuchMethodException if the method could not be found */ private static Method getMethod(final Object instanceOrClass, final String methodName, final Class<?>[] parameterTypes) throws NoSuchMethodException { Class<?> type; type = getClass(instanceOrClass); Method accessMethod = getMethod(type, methodName, parameterTypes); accessMethod.setAccessible(true); return accessMethod; }
/** * Gets the given arguments corrected to match the given methodSignature. Correction is necessary for array arguments not to be * mistaken by varargs. * * @param parameterTypes the method signatue the given arguments should match * @param arguments the arguments that should be corrected * @return the corrected arguments */ private static Object[] getCorrectedArguments(Class<?>[] parameterTypes, Object[] arguments) { if (arguments == null) return arguments; if (parameterTypes.length > arguments.length) return arguments; if (parameterTypes.length < arguments.length) return getCorrectedArguments(parameterTypes, new Object[] {arguments}); Object[] correctedArguments = new Object[arguments.length]; int currentArgument = 0; for (Class<?> parameterType : parameterTypes) { correctedArguments[currentArgument] = getCorrectedArgument(parameterType, arguments[currentArgument]); currentArgument++; } return correctedArguments; }
/** * Gets the value of the named field and returns it as an object. If instanceOrClass is a class then a static field is returned. * * @param instanceOrClass the instance or class to get the field from * @param fieldName the name of the field * @return an object representing the value of the field * @throws NoSuchFieldException if the field does not exist */ public static Object getValue(final Object instanceOrClass, final String fieldName) throws NoSuchFieldException { Field field = getField(instanceOrClass, fieldName); try { return field.get(instanceOrClass); } catch (IllegalAccessException e) { assert false : "getField() should have setAccessible(true), so an IllegalAccessException should not occur in this place"; return null; } }
/** * Calls a method on the given object instance with the given arguments. Arguments can be object types or representations for * primitives. * * @param instanceOrClass the instance or class to invoke the method on * @param methodSignature the name of the method and the parameters <br> * (e.g. "myMethod(java.lang.String, com.company.project.MyObject)") * @param arguments an array of objects to pass as arguments * @return the return value of this method or null if void * @throws IllegalAccessException if the method is inaccessible * @throws InvocationTargetException if the underlying method throws an exception. * @throws NoSuchMethodException if no method with the given <code>methodSignature</code> could be found * @throws IllegalArgumentException if an argument couldn't be converted to match the expected type */ public static Object invokeMethod(final Object instanceOrClass, final String methodSignature, final Object[] arguments) throws IllegalArgumentException, IllegalAccessException, InvocationTargetException, NoSuchMethodException { if ((methodSignature.indexOf('(') == -1) || (methodSignature.indexOf('(') >= methodSignature.indexOf(')'))) throw new NoSuchMethodException(methodSignature); Class<?>[] parameterTypes = getParameterTypes(methodSignature); return getMethod(instanceOrClass, getMethodName(methodSignature), parameterTypes).invoke(instanceOrClass, getCorrectedArguments(parameterTypes, arguments)); }
/** * Gets the signatures of all methods (public, private, protected, default) of the given instance or class. This includes as well * all methods (public, private, protected, default) of all its super classes. This does not include constructors. * * @param instanceOrClass the instance or class to get the method signatures of * @return the collection of method signatures of the given instance or class */ public static Collection<String> getMethodSignatures(final Object instanceOrClass) { if (instanceOrClass == null) return Collections.EMPTY_LIST; Class<?> clazz = getClass(instanceOrClass); Method[] methods = clazz.getDeclaredMethods(); Collection<String> methodSignatures = new ArrayList<String>(methods.length + Object.class.getDeclaredMethods().length); for (Method method : methods) { methodSignatures.add(method.getName() + "(" + getParameterTypesAsString(method.getParameterTypes()) + ")"); } methodSignatures.addAll(getMethodSignatures(clazz.getSuperclass())); return methodSignatures; }
/** * Returns a string representation of the given object. The string has the following format: "<classname> {<attributes and values>}" * whereas <attributes and values> is a comma separated list with <attributeName>=<attributeValue> <atributes and values> includes * all attributes of the objects class followed by the attributes of its superclass (if any) and so on. * * @param instanceOrClass the object or class to get a string representation of * @return a string representation of the given object */ public static String toString(final Object instanceOrClass) { Collection<String> fields = getFieldNames(instanceOrClass); if (fields.isEmpty()) return getClass(instanceOrClass).getName(); StringBuffer stringBuffer = new StringBuffer(); stringBuffer.append(getClass(instanceOrClass).getName() + " {"); for (String fieldName : fields) { try { stringBuffer.append(fieldName + "=" + getValue(instanceOrClass, fieldName) + ", "); } catch (NoSuchFieldException e) { assert false : "It should always be possible to get a field that was just here"; } } stringBuffer.replace(stringBuffer.lastIndexOf(", "), stringBuffer.length(), "}"); return stringBuffer.toString(); }
/** * Gets the name of all fields (public, private, protected, default) of the given instance or class. This includes as well all * fields (public, private, protected, default) of all its super classes. * * @param instanceOrClass the instance or class to get the fields of * @return the collection of field names of the given instance or class */ public static Collection<String> getFieldNames(final Object instanceOrClass) { if (instanceOrClass == null) return Collections.EMPTY_LIST; Class<?> clazz = getClass(instanceOrClass); Field[] fields = clazz.getDeclaredFields(); Collection<String> fieldNames = new ArrayList<String>(fields.length); for (Field field : fields) { fieldNames.add(field.getName()); } fieldNames.addAll(getFieldNames(clazz.getSuperclass())); return fieldNames; }
/** * Return the named field from the given instance or class. Returns a static field if instanceOrClass is a class. * * @param instanceOrClass the instance or class to get the field from * @param fieldName the name of the field to get * @return the field * @throws NoSuchFieldException if no such field can be found * @throws InvalidParameterException if instanceOrClass was null */ private static Field getField(final Object instanceOrClass, final String fieldName) throws NoSuchFieldException, InvalidParameterException { if (instanceOrClass == null) throw new InvalidParameterException("Can't get field on null object/class"); Class<?> type = getClass(instanceOrClass); try { Field field = type.getDeclaredField(fieldName); field.setAccessible(true); return field; } catch (NoSuchFieldException e) { if (type.getSuperclass() == null) throw e; return getField(type.getSuperclass(), fieldName); } }
/** * Gets the class with the given className. * * @param className the name of the class to get * @return the class for the given className * @throws ClassNotFoundException if the class could not be found */ private static Class<?> getClassForName(final String className) throws ClassNotFoundException { if (className.indexOf('[') > -1) { Class<?> clazz = getClassForName(className.substring(0, className.indexOf('['))); return Array.newInstance(clazz, 0).getClass(); } if (className.indexOf("...") > -1) { Class<?> clazz = getClassForName(className.substring(0, className.indexOf("..."))); return Array.newInstance(clazz, 0).getClass(); } try { return Class.forName(className, false, Thread.currentThread().getContextClassLoader()); } catch (ClassNotFoundException e) { return getSpecialClassForName(className); } }
/** * Gets the types of the given parameters. If the parameters don't match the given methodSignature an IllegalArgumentException is * thrown. * * @param methodSignature the signature of the method * @return the parameter types as class[] * @throws NoSuchMethodException if the method could not be found * @throws IllegalArgumentException if one of the given parameters doesn't math the given methodSignature */ private static Class<?>[] getParameterTypes(final String methodSignature) throws NoSuchMethodException, IllegalArgumentException { String signature = getSignatureWithoutBraces(methodSignature); StringTokenizer tokenizer = new StringTokenizer(signature, ", *"); Class<?>[] typesInSignature = new Class[tokenizer.countTokens()]; for (int x = 0; tokenizer.hasMoreTokens(); x++) { String className = tokenizer.nextToken(); try { typesInSignature[x] = getClassForName(className); } catch (ClassNotFoundException e) { NoSuchMethodException noSuchMethodException = new NoSuchMethodException(methodSignature); noSuchMethodException.initCause(e); throw noSuchMethodException; } } return typesInSignature; }
/** * Gets the name of all fields (public, private, protected, default) of the given instance or class. This includes as well all * fields (public, private, protected, default) of all its super classes. * * @param instanceOrClass the instance or class to get the fields of * @return the collection of field names of the given instance or class * * @see PrivilegedAccessor#getFieldNames(Object) */ public static Collection<String> getFieldNames(final Object instanceOrClass) { return PrivilegedAccessor.getFieldNames(instanceOrClass); }
/** * Gets the signatures of all methods (public, private, protected, default) of the given instance or class. This includes as well * all methods (public, private, protected, default) of all its super classes. This does not include constructors. * * @param instanceOrClass the instance or class to get the method signatures of * @return the collection of method signatures of the given instance or class * * @see PrivilegedAccessor#getMethodSignatures(Object) */ public static Collection<String> getMethodSignatures(final Object instanceOrClass) { return PrivilegedAccessor.getMethodSignatures(instanceOrClass); }
/** * Instantiates an object of the given class with the given arguments and the given argument types. If you want to instantiate a * member class, you must provide the object it is a member of as first argument. * * * @param fromClass the class to instantiate an object from * @param args the arguments to pass to the constructor * @param argumentTypes the fully qualified types of the arguments of the constructor * @return an object of the given type * @throws IllegalArgumentException if the number of actual and formal parameters differ; if an unwrapping conversion for primitive * arguments fails; or if, after possible unwrapping, a parameter value cannot be converted to the corresponding formal * parameter type by a method invocation conversion. * @throws IllegalAccessException if this Constructor object enforces Java language access control and the underlying constructor is * inaccessible. * @throws InvocationTargetException if the underlying constructor throws an exception. * @throws NoSuchMethodException if the constructor could not be found * @throws InstantiationException if the class that declares the underlying constructor represents an abstract class. * * @see PrivilegedAccessor#instantiate(Class,Object[]) */ public static <T> T instantiate(final Class<? extends T> fromClass, final Class<?>[] argumentTypes, final Object[] args) throws IllegalArgumentException, InstantiationException, IllegalAccessException, InvocationTargetException, NoSuchMethodException { return getConstructor(fromClass, argumentTypes).newInstance(args); }
/** * Return the named method with a method signature matching classTypes from the given class. * * @param type the class to get the method from * @param methodName the name of the method to get * @param parameterTypes the parameter-types of the method to get * @return the method * @throws NoSuchMethodException if the method could not be found */ private static Method getMethod(final Class<?> type, final String methodName, final Class<?>[] parameterTypes) throws NoSuchMethodException { try { return type.getDeclaredMethod(methodName, parameterTypes); } catch (NoSuchMethodException e) { if (type.getSuperclass() == null) throw e; return getMethod(type.getSuperclass(), methodName, parameterTypes); } }