/** * Finds a method by reflection. This iterates all methods of the class, comparing names and * parameter types. Unlike the method Class.getMethod(String, Class ...), this method is able to * match primitive and wrapper types. If no appropriate method is found, a ConfigurationError is * raised. * * @param type * @param methodName * @param paramTypes * @return a method with matching names and parameters */ public static Method getMethod(Class<?> type, String methodName, Class<?>... paramTypes) { Method method = findMethod(type, methodName, paramTypes); if (method == null) throw new ConfigurationError( "method not found in class " + type.getName() + ": " + methodName + '(' + ArrayFormat.format(paramTypes) + ')'); return method; }
@SuppressWarnings({"unchecked", "rawtypes"}) public static <T> T newInstance(Class<T> type, boolean strict, Object... parameters) { if (parameters.length == 0) return newInstanceFromDefaultConstructor(type); Constructor<T> constructorToUse = null; try { Constructor<T>[] constructors = (Constructor<T>[]) type.getConstructors(); List<Constructor<T>> candidates = new ArrayList<Constructor<T>>(constructors.length); int paramCount = parameters.length; for (Constructor<T> constructor : constructors) if (constructor.getParameterTypes().length == paramCount) candidates.add(constructor); if (candidates.size() == 1) constructorToUse = candidates.get(0); else if (candidates.size() == 0) throw new ConfigurationError( "No constructor with " + paramCount + " parameters found for " + type); else { // there are several candidates - find the first one with matching types Class<?>[] paramTypes = new Class[parameters.length]; for (int i = 0; i < parameters.length; i++) paramTypes[i] = parameters[i].getClass(); for (Constructor c : type.getConstructors()) { if (typesMatch(c.getParameterTypes(), paramTypes)) { constructorToUse = c; break; } } // there is no ideal match if (constructorToUse == null) { if (strict) throw new NoSuchMethodException( "No appropriate constructor found: " + type + '(' + ArrayFormat.format(", ", paramTypes) + ')'); Exception mostRecentException = null; for (Constructor<T> candidate : candidates) { try { return newInstance(candidate, strict, parameters); } catch (Exception e) { mostRecentException = e; logger.warn("Exception in constructor call: " + candidate, e); continue; // ignore exception and try next constructor } } // no constructor could be called without exception String errMsg = (mostRecentException != null ? "None of these constructors could be called without exception: " + candidates + ", latest exception: " + mostRecentException : type + " has no appropriate constructor for the arguments " + ArrayFormat.format(", ", parameters)); throw new ConfigurationError(errMsg); } } if (!strict) parameters = convertArray(parameters, constructorToUse.getParameterTypes()); return newInstance(constructorToUse, parameters); } catch (SecurityException e) { throw ExceptionMapper.configurationException(e, constructorToUse); } catch (NoSuchMethodException e) { throw ExceptionMapper.configurationException(e, type); } }