calls a Static Method on the given CLass

@param clazz Class to call Method on it
@param methodName Name of the Method to get
@param args Arguments of the Method to get
@return return return value of the called Method
@throws PageException
8236
public static Object callStaticMethod(Class clazz, String methodName, Object[] args) throws PageException {
	try {
	    return getMethodInstance(null, clazz, methodName, args).invoke(null);
	}
	catch (InvocationTargetException e) {
	    Throwable target = e.getTargetException();
	    if (target instanceof PageException) throw (PageException) target;
	    throw Caster.toPageException(e.getTargetException());
	}
	catch (Exception e) {
	    throw Caster.toPageException(e);
	}
    }
954360
public static Method getMethod(Class<?> clazz, String name) {
        return getMethod(clazz, name, false);
    }
452210
public static String call(PageContext pc, Object object) throws PageException {
	return call(pc, object, null, true, 9999, null, null, null, null, 9999, true, true);
    }
1056897
public static Method[] collectMethods(Class<?> clazz, String name) {
        final List<Method> result = new ArrayList<>();
        for (Method m: clazz.getMethods()) {
            if (m.getName().equals(name)) result.add(m);
        }
        return result.toArray(new Method[result.size()]);
    }
723920
@Nullable
  public static Method getMethodByName(Class<?> clazz, String name) {
    for (Method method : clazz.getMethods())
      if (method.getName().equals(name))
        return method;

    return null;
  }
866901
public static String call(PageContext pc, Object var, boolean serializeQueryByColumns) throws PageException {
	return _call(pc, var, serializeQueryByColumns, pc.getWebCharset());
    }
1245001
public static Map<RouteDefinition, Method> get(Class clazz) {

		Map<RouteDefinition, Method> out = new HashMap<>();

		Map<RouteDefinition, Method> candidates = collect(clazz);
		// Final check if definitions are OK
		for (RouteDefinition definition : candidates.keySet()) {

			if (definition.getMethod() == null) { // skip non REST methods
				continue;
			}

			Method method = candidates.get(definition);
			Assert.notNull(definition.getRoutePath(), getClassMethod(clazz, method) + " - Missing route @Path!");

			int bodyParamCount = 0;
			for (MethodParameter param : definition.getParameters()) {
				if (bodyParamCount > 0 && (ParameterType.body.equals(param.getType()) || ParameterType.unknown.equals(param.getType()))) {
					// OK we have to body params ...
					throw new IllegalArgumentException(getClassMethod(clazz, method) + " - to many body arguments given. " +
					                                   "Missing argument annotation (@PathParam, @QueryParam, @FormParam, @HeaderParam, @CookieParam or @Context) for: " +
					                                   param.getType() + " " + param.getName() + "!");
				}

				if (ParameterType.unknown.equals(param.getType())) { // proclaim as body param
					// check if method allows for a body param
					Assert.isTrue(definition.requestHasBody(), getClassMethod(clazz, method) + " - " +
					                                           "Missing argument annotation (@PathParam, @QueryParam, @FormParam, @HeaderParam, @CookieParam or @Context) for: " +
					                                           param.getName() + "!");

					param.setType(ParameterType.body);
				}

				if (ParameterType.body.equals(param.getType())) {
					bodyParamCount++;
				}
			}

			out.put(definition, method);
		}

		return out;
	}
269209
public static MethodInstance getMethodInstanceEL(Object objMaybeNull, Class clazz, Collection.Key methodName, Object[] args) {
	checkAccessibility(objMaybeNull, clazz, methodName);
	args = cleanArgs(args);

	Method[] methods = mStorage.getMethods(clazz, methodName, args.length);// getDeclaredMethods(clazz);

	if (methods != null) {
	    Class[] clazzArgs = getClasses(args);
	    // exact comparsion
	    // print.e("exact:"+methodName);
	    outer: for (int i = 0; i < methods.length; i++) {
		if (methods[i] != null) {
		    Class[] parameterTypes = methods[i].getParameterTypes();
		    for (int y = 0; y < parameterTypes.length; y++) {
			if (toReferenceClass(parameterTypes[y]) != clazzArgs[y]) continue outer;
		    }
		    return new MethodInstance(methods[i], args);
		}
	    }
	    // like comparsion
	    // MethodInstance mi=null;
	    // print.e("like:"+methodName);
	    outer: for (int i = 0; i < methods.length; i++) {
		if (methods[i] != null) {
		    Class[] parameterTypes = methods[i].getParameterTypes();
		    for (int y = 0; y < parameterTypes.length; y++) {
			if (!like(clazzArgs[y], toReferenceClass(parameterTypes[y]))) continue outer;
		    }
		    return new MethodInstance(methods[i], args);
		}
	    }

	    // convert comparsion
	    // print.e("convert:"+methodName);
	    MethodInstance mi = null;
	    int _rating = 0;
	    outer: for (int i = 0; i < methods.length; i++) {
		if (methods[i] != null) {
		    RefInteger rating = (methods.length > 1) ? new RefIntegerImpl(0) : null;
		    Class[] parameterTypes = methods[i].getParameterTypes();
		    Object[] newArgs = new Object[args.length];
		    for (int y = 0; y < parameterTypes.length; y++) {
			try {
			    newArgs[y] = convert(args[y], toReferenceClass(parameterTypes[y]), rating);
			}
			catch (PageException e) {
			    continue outer;
			}
		    }
		    if (mi == null || rating.toInt() > _rating) {
			if (rating != null) _rating = rating.toInt();
			mi = new MethodInstance(methods[i], newArgs);
		    }
		    // return new MethodInstance(methods[i],newArgs);
		}
	    }
	    return mi;
	}
	return null;
    }
57659
public static Object call(PageContext pc, Object coll, Collection.Key methodName, Object[] args, short[] types, String[] strTypes) throws PageException {

	// look for members
	short type;
	String strType;
	Map<Key, FunctionLibFunction> members = null;
	for (int i = 0; i < types.length; i++) {
	    type = types[i];
	    strType = strTypes[i];
	    members = getMembers(pc, type);
	    FunctionLibFunction member = members.get(methodName);
	    if (member != null) {
		List<FunctionLibFunctionArg> _args = member.getArg();
		if (args.length < _args.size()) {
		    ArrayList<Ref> refs = new ArrayList<Ref>();

		    int pos = member.getMemberPosition();
		    FunctionLibFunctionArg flfa;
		    Iterator<FunctionLibFunctionArg> it = _args.iterator();
		    int glbIndex = 0, argIndex = -1;
		    while (it.hasNext()) {
			glbIndex++;
			flfa = it.next();
			if (glbIndex == pos) {
			    refs.add(new Casting(strType, type, coll));
			}
			else if (args.length > ++argIndex) { // careful, argIndex is only incremented when condition above is false
			    refs.add(new Casting(flfa.getTypeAsString(), flfa.getType(), args[argIndex]));
			}
		    }
		    return new BIFCall(coll, member, refs.toArray(new Ref[refs.size()])).getValue(pc);
		}

	    }
	}

	// do reflection
	if (pc.getConfig().getSecurityManager().getAccess(lucee.runtime.security.SecurityManager.TYPE_DIRECT_JAVA_ACCESS) == lucee.runtime.security.SecurityManager.VALUE_YES) {
	    if (!(coll instanceof Undefined)) {
		Object res = callMethod(coll, methodName, args);
		if (res != DEFAULT) return res;
	    }
	}

	// merge
	if (types.length > 1) {
	    Map<Key, FunctionLibFunction> tmp;
	    members = null;
	    for (int i = 0; i < types.length; i++) {
		tmp = getMembers(pc, types[i]);
		if (members == null) members = tmp;
		else {
		    Iterator<Entry<Key, FunctionLibFunction>> it = tmp.entrySet().iterator();
		    Entry<Key, FunctionLibFunction> e;
		    while (it.hasNext()) {
			e = it.next();
			members.put(e.getKey(), e.getValue());
		    }
		}
	    }
	}
	Set<Key> set = members.keySet();
	String msg = ExceptionUtil.similarKeyMessage(set.toArray(new Key[set.size()]), methodName.getString(), "function", "functions", "Object", true);
	throw new ExpressionException(msg);
	// throw new ExpressionException("No matching function member ["+methodName+"] found, available
	// function members are ["+
	// lucee.runtime.type.util.ListUtil.sort(CollectionUtil.getKeyList(members.keySet().iterator(),
	// ","),"textnocase","asc",",")+"]");
    }
198382
static double callLegacy(PageContext pc, Array array, Object value) throws PageException {
	String str = Caster.toString(value, null);
	if (str != null) return ArrayUtil.arrayContainsIgnoreEmpty(array, str, false) + 1;
	return ArrayFind.call(pc, array, value);
    }
122155
public static void invokeMain(String className, String[] args) {
        try {
            Class<?> clazz = null;
            if (ClassServiceUtility.getClassService().getClassFinder(null) != null)
                clazz = ClassServiceUtility.getClassService().getClassFinder(null).findClass(className, null);
            if (clazz == null)
                clazz = Class.forName(className);

            Method method = clazz.getMethod("main", PARAMS);
            Object[] objArgs = new Object[] {args};
            method.invoke(null, objArgs);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
636591
public static Method getMethodByName(Class<?> clazz, String methodName) throws SecurityException {
		return getMethodByName(clazz, false, methodName);
	}
350583
public static <T> T invoke(String className, String methodName, Object[] args) {
		return invoke(className, methodName, false, args);
	}
1030291
public static <T> T invokeMethodByName(final Object obj, final String methodName, final Object[] args) {
		Method method = getAccessibleMethodByName(obj.getClass(), methodName);
		if (method == null) {
			throw new IllegalArgumentException(
					"Could not find method [" + methodName + "] on class [" + obj.getClass() + ']');
		}
		return invokeMethod(obj, method, args);
	}
367308
private static Method getMethod(Class<?> clazz, String name, Class<?>... paramTypes) {
        try {
            return clazz.getMethod(name, paramTypes);
        } catch (NoSuchMethodException e) {
            return getMethod0(clazz, name, paramTypes);
        }
    }
609122
@Override
  public final Method retrieveMethod(final Class<?> pClazz,
    final String pMethodName) throws Exception {
    for (Method mfd : pClazz.getDeclaredMethods()) {
      if (mfd.getName().equals(pMethodName)) {
        return mfd;
      }
    }
    final Class<?> superClazz = pClazz.getSuperclass();
    Method method = null;
    if (superClazz != null && superClazz != java.lang.Object.class) {
      method = retrieveMethod(superClazz, pMethodName);
    }
    if (method == null) {
      throw new Exception("There is no method " + pMethodName + " in class "
        + pClazz); //TO-DO class must be original
    }
    return method;
  }
1297515
public com.groupon.odo.proxylib.models.Method getMethod(String className, String methodName) throws Exception {
        // TODO: fix this so it returns the right override ID
        com.groupon.odo.proxylib.models.Method m = null;

        // calls getClass first in case the loaded class needs to be invalidated
        Class<?> gottenClass = getClass(className);
        ClassInformation classInfo = classInformation.get(className);

        String fullName = className + "." + methodName;
        if (methodInformation.containsKey(fullName)) {
            m = methodInformation.get(fullName);
        } else {
            logger.info("Getting method info: {}", fullName);

            // Make a new classpool with the system classpath URLS
            // We create a new classpool each time since we want to reload plugin information in case it has changed.
            // Once a method is loaded this should not get called so the extra expense is not always taken as a hit
            ClassPool classPool = new ClassPool();
            ClassLoader sysClassLoader = Thread.currentThread().getContextClassLoader();

            //Get the URLs
            URL[] urls = ((URLClassLoader) sysClassLoader).getURLs();
            for (int i = 0; i < urls.length; i++) {
                try {
                    // insert all classpaths into the javassist classpool
                    File f1 = new File(urls[i].getFile());

                    if (f1.exists()) {
                        // only add if file exists to avoid an uncatchable exception in Java 8
                        classPool.insertClassPath(urls[i].getFile());
                    }
                } catch (NotFoundException e) {
                    e.printStackTrace();
                }
            }
            classPool.insertClassPath(classInfo.pluginPath);

            // load method information
            Method[] methods = gottenClass.getDeclaredMethods();
            for (Method method : methods) {
                if (method.getName().compareTo(methodName) != 0) {
                    continue;
                }

                try {
                    // get annotation information
                    Annotation[] annotations = method.getAnnotations();
                    for (Annotation annotation : annotations) {
                        com.groupon.odo.proxylib.models.Method newMethod = new com.groupon.odo.proxylib.models.Method();
                        newMethod.setClassName(className);
                        newMethod.setMethodName(methodName);
                        newMethod.setMethod(method);
                        newMethod.setMethodType(annotation.annotationType().toString());

                        String[] argNames = null;
                        String[] defaultArgs = null;
                        String description = null;

                        // Convert to the right type and get annotation information
                        if (annotation.annotationType().toString().endsWith(Constants.PLUGIN_RESPONSE_OVERRIDE_CLASS)) {
                            ResponseOverride roAnnotation = (ResponseOverride) annotation;
                            newMethod.setHttpCode(roAnnotation.httpCode());
                            description = roAnnotation.description();
                            argNames = roAnnotation.parameters();
                            defaultArgs = new String[0];
                            newMethod.setOverrideVersion(1);
                        } else if (annotation.annotationType().toString().endsWith(Constants.PLUGIN_RESPONSE_OVERRIDE_V2_CLASS)) {
                            com.groupon.odo.plugin.v2.ResponseOverride roAnnotation = (com.groupon.odo.plugin.v2.ResponseOverride) annotation;
                            description = roAnnotation.description();
                            argNames = roAnnotation.parameters();
                            defaultArgs = roAnnotation.argDefaults();
                            newMethod.setBlockRequest(roAnnotation.blockRequest());
                            newMethod.setOverrideVersion(2);
                        } else {
                            continue;
                        }

                        // identify arguments
                        // first arg is always a reserved that we skip
                        ArrayList<String> params = new ArrayList<String>();
                        if (method.getParameterTypes().length > 1) {
                            for (int x = 1; x < method.getParameterTypes().length; x++) {
                                params.add(method.getParameterTypes()[x].getName());
                            }
                        }
                        newMethod.setMethodArguments(params.toArray(new Object[0]));
                        newMethod.setMethodArgumentNames(argNames);
                        newMethod.setMethodDefaultArguments(defaultArgs);
                        newMethod.setDescription(description);
                        newMethod.setIdString(className + "." + methodName);

                        methodInformation.put(fullName, newMethod);
                        m = newMethod;
                    }

                    break;
                } catch (Exception e) {
                    // in this case we just return null since the method would be unuseable
                    return null;
                }
            }
        }

        return m;
    }