📄 metaclasshelper.java
字号:
} } else if (argumentArray.length>paramTypes.length) { // the number of arguments is too big, wrap all exceeding elements // in an array, but keep the old elements that are no vargs Object[] newArgs = new Object[paramTypes.length]; // copy arguments that are not a varg System.arraycopy(argumentArray,0,newArgs,0,paramTypes.length-1); // create a new array for the vargs and copy them int numberOfVargs = argumentArray.length-paramTypes.length; Object vargs = makeCommonArray(argumentArray,paramTypes.length-1,vargsClass); newArgs[newArgs.length-1] = vargs; return newArgs; } else { throw new GroovyBugError("trying to call a vargs method without enough arguments"); } } private static GroovyRuntimeException createExceptionText(String init, MetaMethod method, Object object, Object[] args, Throwable reason, boolean setReason) { return new GroovyRuntimeException( init + method + " on: " + object + " with arguments: " + InvokerHelper.toString(args) + " reason: " + reason, setReason?reason:null); } public static Object doMethodInvoke(Object object, MetaMethod method, Object[] argumentArray) { Class[] paramTypes = method.getParameterTypes(); argumentArray = coerceArgumentsToClasses(argumentArray,paramTypes); try { return method.invoke(object, argumentArray); } catch (InvocationTargetException e) { throw new InvokerInvocationException(e); } catch (IllegalAccessException e) { throw createExceptionText("could not access method: ", method, object, argumentArray, e, true); } catch (IllegalArgumentException e) { //TODO: test if this is ok with new MOP, should be changed! // we don't want the exception being unwrapped if it is a IllegalArgumentException // but in the case it is for example a IllegalThreadStateException, we want the unwrapping // from the runtime //Note: the reason we want unwrapping sometimes and sometimes not is that the method // invokation tries to invoke the method with and then reacts with type transformation // if the invokation failed here. This is ok for IllegalArgumentException, but it is // possible that a Reflector will be used to execute the call and then an Exception from inside // the method is not wrapped in a InvocationTargetException and we will end here. boolean setReason = e.getClass() != IllegalArgumentException.class; throw createExceptionText("failed to invoke method: ", method, object, argumentArray, e, setReason); } catch (RuntimeException e) { throw e; } catch (Exception e) { throw createExceptionText("failed to invoke method: ", method, object, argumentArray, e, true); } } protected static String getClassName(Object object) { return (object instanceof Class) ? ((Class)object).getName() : object.getClass().getName(); } /** * Returns a callable object for the given method name on the object. * The object acts like a Closure in that it can be called, like a closure * and passed around - though really its a method pointer, not a closure per se. */ public static Closure getMethodPointer(Object object, String methodName) { return new MethodClosure(object, methodName); } public static Class[] getParameterTypes(Object methodOrConstructor) { if (methodOrConstructor instanceof MetaMethod) { MetaMethod method = (MetaMethod) methodOrConstructor; return method.getParameterTypes(); } if (methodOrConstructor instanceof Method) { Method method = (Method) methodOrConstructor; return method.getParameterTypes(); } if (methodOrConstructor instanceof Constructor) { Constructor constructor = (Constructor) methodOrConstructor; return constructor.getParameterTypes(); } throw new IllegalArgumentException("Must be a Method or Constructor"); } protected static boolean isAssignableFrom(Class classToTransformTo, Class classToTransformFrom) { if (classToTransformFrom==null) return true; classToTransformTo = autoboxType(classToTransformTo); classToTransformFrom = autoboxType(classToTransformFrom); if (classToTransformTo == classToTransformFrom) { return true; } // note: there is not coercion for boolean and char. Range matters, precision doesn't else if (classToTransformTo == Integer.class) { if ( classToTransformFrom == Integer.class || classToTransformFrom == Short.class || classToTransformFrom == Byte.class || classToTransformFrom == BigInteger.class) return true; } else if (classToTransformTo == Double.class) { if ( classToTransformFrom == Double.class || classToTransformFrom == Integer.class || classToTransformFrom == Long.class || classToTransformFrom == Short.class || classToTransformFrom == Byte.class || classToTransformFrom == Float.class || classToTransformFrom == BigDecimal.class || classToTransformFrom == BigInteger.class) return true; } else if (classToTransformTo == BigDecimal.class) { if ( classToTransformFrom == Double.class || classToTransformFrom == Integer.class || classToTransformFrom == Long.class || classToTransformFrom == Short.class || classToTransformFrom == Byte.class || classToTransformFrom == Float.class || classToTransformFrom == BigDecimal.class || classToTransformFrom == BigInteger.class) return true; } else if (classToTransformTo == BigInteger.class) { if ( classToTransformFrom == Integer.class || classToTransformFrom == Long.class || classToTransformFrom == Short.class || classToTransformFrom == Byte.class || classToTransformFrom == BigInteger.class) return true; } else if (classToTransformTo == Long.class) { if ( classToTransformFrom == Long.class || classToTransformFrom == Integer.class || classToTransformFrom == Short.class || classToTransformFrom == Byte.class) return true; } else if (classToTransformTo == Float.class) { if ( classToTransformFrom == Float.class || classToTransformFrom == Integer.class || classToTransformFrom == Long.class || classToTransformFrom == Short.class || classToTransformFrom == Byte.class) return true; } else if (classToTransformTo == Short.class) { if ( classToTransformFrom == Short.class || classToTransformFrom == Byte.class) return true; } else if (classToTransformTo==String.class) { if ( classToTransformFrom == String.class || GString.class.isAssignableFrom(classToTransformFrom)) return true; } boolean answer = classToTransformTo.isAssignableFrom(classToTransformFrom); return answer; } public static boolean isGenericSetMethod(MetaMethod method) { return (method.getName().equals("set")) && method.getParameterTypes().length == 2; } protected static boolean isSuperclass(Class claszz, Class superclass) { while (claszz!=null) { if (claszz==superclass) return true; claszz = claszz.getSuperclass(); } return false; } public static boolean isValidMethod(Class[] paramTypes, Class[] arguments, boolean includeCoerce) { if (arguments == null) { return true; } int size = arguments.length; if ( (size>=paramTypes.length || size==paramTypes.length-1) && paramTypes.length>0 && paramTypes[paramTypes.length-1].isArray()) { // first check normal number of parameters for (int i = 0; i < paramTypes.length-1; i++) { if (isAssignableFrom(paramTypes[i], arguments[i])) continue; return false; } // check varged Class clazz = paramTypes[paramTypes.length-1].getComponentType(); for (int i=paramTypes.length; i<size; i++) { if (isAssignableFrom(clazz, arguments[i])) continue; return false; } return true; } else if (paramTypes.length == size) { // lets check the parameter types match for (int i = 0; i < size; i++) { if (isAssignableFrom(paramTypes[i], arguments[i])) continue; return false; } return true; } else if (paramTypes.length == 1 && size == 0) { return true; } return false; } public static boolean isValidMethod(Object method, Class[] arguments, boolean includeCoerce) { Class[] paramTypes = getParameterTypes(method); return isValidMethod(paramTypes, arguments, includeCoerce); } public static boolean isVargsMethod(Class[] paramTypes, Object[] arguments) { if (paramTypes.length==0) return false; if (!paramTypes[paramTypes.length-1].isArray()) return false; // -1 because the varg part is optional if (paramTypes.length-1==arguments.length) return true; if (paramTypes.length-1>arguments.length) return false; if (arguments.length>paramTypes.length) return true; // only case left is arguments.length==paramTypes.length Object last = arguments[arguments.length-1]; if (last==null) return true; Class clazz = last.getClass(); if (clazz.equals(paramTypes[paramTypes.length-1])) return false; return true; } public static void logMethodCall(Object object, String methodName, Object[] arguments) { String className = getClassName(object); String logname = "methodCalls." + className + "." + methodName; Logger objLog = Logger.getLogger(logname); if (! objLog.isLoggable(Level.FINER)) return; StringBuffer msg = new StringBuffer(methodName); msg.append("("); if (arguments != null){ for (int i = 0; i < arguments.length;) { msg.append(normalizedValue(arguments[i])); if (++i < arguments.length) { msg.append(","); } } } msg.append(")"); objLog.logp(Level.FINER, className, msg.toString(), "called from MetaClass.invokeMethod"); } protected static String normalizedValue(Object argument) { String value; try { value = argument.toString(); if (value.length() > MAX_ARG_LEN){ value = value.substring(0,MAX_ARG_LEN-2) + ".."; } if (argument instanceof String){ value = "\'"+value+"\'"; } } catch (Exception e) { value = shortName(argument); } return value; } public static boolean parametersAreCompatible(Class[] arguments, Class[] parameters) { if (arguments.length!=parameters.length) return false; for (int i=0; i<arguments.length; i++) { if (!isAssignableFrom(parameters[i],arguments[i])) return false; } return true; } protected static String shortName(Object object) { if (object == null || object.getClass()==null) return "unknownClass"; String name = getClassName(object); if (name == null) return "unknownClassName"; // *very* defensive... int lastDotPos = name.lastIndexOf('.'); if (lastDotPos < 0 || lastDotPos >= name.length()-1) return name; return name.substring(lastDotPos+1); } public static Class[] wrap(Class[] classes) { Class[] wrappedArguments = new Class[classes.length]; for (int i = 0; i < wrappedArguments.length; i++) { Class c = classes[i]; if (c==null) continue; if (c.isPrimitive()) { if (c==Integer.TYPE) { c=Integer.class; } else if (c==Byte.TYPE) { c=Byte.class; } else if (c==Long.TYPE) { c=Long.class; } else if (c==Double.TYPE) { c=Double.class; } else if (c==Float.TYPE) { c=Float.class; } } else if (isSuperclass(c,GString.class)) { c = String.class; } wrappedArguments[i]=c; } return wrappedArguments; }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -