📄 metaclasshelper.java
字号:
/** * @return the method with 1 parameter which takes the most general type of * object (e.g. Object) ignoring primitve types */ public static Object chooseMostGeneralMethodWith1NullParam(List methods) { // lets look for methods with 1 argument which matches the type of the // arguments Class closestClass = null; Object answer = null; for (Iterator iter = methods.iterator(); iter.hasNext();) { Object method = iter.next(); Class[] paramTypes = getParameterTypes(method); int paramLength = paramTypes.length; if (paramLength == 1) { Class theType = paramTypes[0]; if (theType.isPrimitive()) continue; if (closestClass == null || isAssignableFrom(theType, closestClass)) { closestClass = theType; answer = method; } } } return answer; } /** * Coerces a GString instance into String if needed * * @return the coerced argument */ protected static Object coerceGString(Object argument, Class clazz) { if (clazz!=String.class) return argument; if (!(argument instanceof GString)) return argument; return argument.toString(); } protected static Object coerceNumber(Object argument, Class param) { if ((Number.class.isAssignableFrom(param) || param.isPrimitive()) && argument instanceof Number) { // Number types Object oldArgument = argument; boolean wasDouble = false; boolean wasFloat = false; if (param == Byte.class || param == Byte.TYPE ) { argument = new Byte(((Number)argument).byteValue()); } else if (param == Double.class || param == Double.TYPE) { wasDouble = true; argument = new Double(((Number)argument).doubleValue()); } else if (param == Float.class || param == Float.TYPE) { wasFloat = true; argument = new Float(((Number)argument).floatValue()); } else if (param == Integer.class || param == Integer.TYPE) { argument = new Integer(((Number)argument).intValue()); } else if (param == Long.class || param == Long.TYPE) { argument = new Long(((Number)argument).longValue()); } else if (param == Short.class || param == Short.TYPE) { argument = new Short(((Number)argument).shortValue()); } else if (param == BigDecimal.class ) { argument = new BigDecimal(String.valueOf((Number)argument)); } else if (param == BigInteger.class) { argument = new BigInteger(String.valueOf((Number)argument)); } if (oldArgument instanceof BigDecimal) { BigDecimal oldbd = (BigDecimal) oldArgument; boolean throwException = false; if (wasDouble) { Double d = (Double) argument; if (d.isInfinite()) throwException = true; } else if (wasFloat) { Float f = (Float) argument; if (f.isInfinite()) throwException = true; } else { BigDecimal newbd = new BigDecimal(String.valueOf((Number)argument)); throwException = !oldArgument.equals(newbd); } if (throwException) throw new IllegalArgumentException(param+" out of range while converting from BigDecimal"); } } return argument; } protected static Object coerceArray(Object argument, Class param) { if (!param.isArray()) return argument; Class argumentClass = argument.getClass(); if (!argumentClass.isArray()) return argument; Class paramComponent = param.getComponentType(); if (paramComponent.isPrimitive()) { if (paramComponent == boolean.class && argumentClass==Boolean[].class) { argument = InvokerHelper.convertToBooleanArray(argument); } else if (paramComponent == byte.class && argumentClass==Byte[].class) { argument = InvokerHelper.convertToByteArray(argument); } else if (paramComponent == char.class && argumentClass==Character[].class) { argument = InvokerHelper.convertToCharArray(argument); } else if (paramComponent == short.class && argumentClass==Short[].class) { argument = InvokerHelper.convertToShortArray(argument); } else if (paramComponent == int.class && argumentClass==Integer[].class) { argument = InvokerHelper.convertToIntArray(argument); } else if (paramComponent == long.class && (argumentClass == Long[].class || argumentClass == Integer[].class)) { argument = InvokerHelper.convertToLongArray(argument); } else if (paramComponent == float.class && (argumentClass == Float[].class || argumentClass == Integer[].class)) { argument = InvokerHelper.convertToFloatArray(argument); } else if (paramComponent == double.class && (argumentClass == Double[].class || argumentClass==Float[].class || BigDecimal.class.isAssignableFrom(argumentClass))) { argument = InvokerHelper.convertToDoubleArray(argument); } } else if (paramComponent==String.class && argument instanceof GString[]) { GString[] strings = (GString[]) argument; String[] ret = new String[strings.length]; for (int i=0; i<strings.length; i++) { ret[i] = strings[i].toString(); } argument = ret; } return argument; } /** * @return true if a method of the same matching prototype was found in the * list */ public static boolean containsMatchingMethod(List list, MetaMethod method) { for (Iterator iter = list.iterator(); iter.hasNext();) { MetaMethod aMethod = (MetaMethod) iter.next(); Class[] params1 = aMethod.getParameterTypes(); Class[] params2 = method.getParameterTypes(); if (params1.length == params2.length) { boolean matches = true; for (int i = 0; i < params1.length; i++) { if (params1[i] != params2[i]) { matches = false; break; } } if (matches) { return true; } } } return false; } /** * param instance array to the type array * @param args * @return */ public static Class[] convertToTypeArray(Object[] args) { if (args == null) return null; int s = args.length; Class[] ans = new Class[s]; for (int i = 0; i < s; i++) { Object o = args[i]; if (o != null) { ans[i] = o.getClass(); } else { ans[i] = null; } } return ans; } /** * @param listenerType * the interface of the listener to proxy * @param listenerMethodName * the name of the method in the listener API to call the * closure on * @param closure * the closure to invoke on the listenerMethodName method * invocation * @return a dynamic proxy which calls the given closure on the given * method name */ public static Object createListenerProxy(Class listenerType, final String listenerMethodName, final Closure closure) { InvocationHandler handler = new ClosureListener(listenerMethodName, closure); return Proxy.newProxyInstance(listenerType.getClassLoader(), new Class[] { listenerType }, handler); } public static Object doConstructorInvoke(Constructor constructor, Object[] argumentArray) { if (log.isLoggable(Level.FINER)){ logMethodCall(constructor.getDeclaringClass(), constructor.getName(), argumentArray); } argumentArray = coerceArgumentsToClasses(argumentArray,constructor.getParameterTypes()); try { return constructor.newInstance(argumentArray); } catch (InvocationTargetException e) { throw new InvokerInvocationException(e); } catch (IllegalArgumentException e) { throw createExceptionText("failed to invoke constructor: ", constructor, argumentArray, e, false); } catch (IllegalAccessException e) { throw createExceptionText("could not access constructor: ", constructor, argumentArray, e, false); } catch (Exception e) { throw createExceptionText("failed to invoke constructor: ", constructor, argumentArray, e, true); } } private static GroovyRuntimeException createExceptionText(String init, Constructor constructor, Object[] argumentArray, Throwable e, boolean setReason) { throw new GroovyRuntimeException( init + constructor + " with arguments: " + InvokerHelper.toString(argumentArray) + " reason: " + e, setReason?e:null); } public static Object[] coerceArgumentsToClasses(Object[] argumentArray, Class[] paramTypes) { // correct argumentArray's length if (argumentArray == null) { argumentArray = EMPTY_ARRAY; } else if (paramTypes.length == 1 && argumentArray.length == 0) { if (isVargsMethod(paramTypes,argumentArray)) argumentArray = new Object[]{Array.newInstance(paramTypes[0].getComponentType(),0)}; else argumentArray = ARRAY_WITH_NULL; } else if (isVargsMethod(paramTypes,argumentArray)) { argumentArray = fitToVargs(argumentArray, paramTypes); } //correct Type for (int i=0; i<argumentArray.length; i++) { Object argument = argumentArray[i]; if (argument==null) continue; Class parameterType = paramTypes[i]; if (parameterType.isInstance(argument)) continue; argument = coerceGString(argument,parameterType); argument = coerceNumber(argument,parameterType); argument = coerceArray(argument,parameterType); argumentArray[i] = argument; } return argumentArray; } private static Object makeCommonArray(Object[] arguments, int offset, Class fallback) { // arguments.leght>0 && !=null Class baseClass = null; for (int i = offset; i < arguments.length; i++) { if (arguments[i]==null) continue; Class argClass = arguments[i].getClass(); if (baseClass==null) { baseClass = argClass; } else { for (;baseClass!=Object.class; baseClass=baseClass.getSuperclass()){ if (baseClass.isAssignableFrom(argClass)) break; } } } if (baseClass==null) { // all arguments were null baseClass = fallback; } Object result = makeArray(null,baseClass,arguments.length-offset); System.arraycopy(arguments,offset,result,0,arguments.length-offset); return result; } private static Object makeArray(Object obj, Class secondary, int length) { Class baseClass = secondary; if (obj!=null) { baseClass = obj.getClass(); } /*if (GString.class.isAssignableFrom(baseClass)) { baseClass = GString.class; }*/ return Array.newInstance(baseClass,length); } /** * this method is called when the number of arguments to a method is greater than 1 * and if the method is a vargs method. This method will then transform the given * arguments to make the method callable * * @param argumentArray the arguments used to call the method * @param paramTypes the types of the paramters the method takes */ private static Object[] fitToVargs(Object[] argumentArray, Class[] paramTypes) { Class vargsClass = autoboxType(paramTypes[paramTypes.length-1].getComponentType()); if (argumentArray.length == paramTypes.length-1) { // the vargs argument is missing, so fill it with an empty array Object[] newArgs = new Object[paramTypes.length]; System.arraycopy(argumentArray,0,newArgs,0,argumentArray.length); Object vargs = makeArray(null,vargsClass,0); newArgs[newArgs.length-1] = vargs; return newArgs; } else if (argumentArray.length==paramTypes.length) { // the number of arguments is correct, but if the last argument // is no array we have to wrap it in a array. if the last argument // is null, then we don't have to do anything Object lastArgument = argumentArray[argumentArray.length-1]; if (lastArgument!=null && !lastArgument.getClass().isArray()) { // no array so wrap it Object vargs = makeArray(lastArgument,vargsClass,1); System.arraycopy(argumentArray,argumentArray.length-1,vargs,0,1); argumentArray[argumentArray.length-1]=vargs; return argumentArray; } else { // we may have to box the arguemnt! return argumentArray;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -