diff --git a/core/src/main/java/lucee/commons/lang/ClassUtil.java b/core/src/main/java/lucee/commons/lang/ClassUtil.java index 6c8b6169f1..8e4354f6f4 100644 --- a/core/src/main/java/lucee/commons/lang/ClassUtil.java +++ b/core/src/main/java/lucee/commons/lang/ClassUtil.java @@ -1032,8 +1032,8 @@ public static ClassLoader getClassLoader(PageContext pc, Class clazz) throws IOE return new lucee.commons.lang.ClassLoaderHelper().getClass().getClassLoader(); } - public static Object newInstance(Class clazz) throws InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException, NoSuchMethodException, - SecurityException, PageException, IOException { + public static Object newInstance(Class clazz) + throws InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException, NoSuchMethodException, SecurityException, PageException { return Reflector.getConstructorInstance(clazz, EMPTY_OBJ, true).invoke(); } } \ No newline at end of file diff --git a/core/src/main/java/lucee/runtime/reflection/Reflector.java b/core/src/main/java/lucee/runtime/reflection/Reflector.java index 73933eab12..c4f2c22252 100755 --- a/core/src/main/java/lucee/runtime/reflection/Reflector.java +++ b/core/src/main/java/lucee/runtime/reflection/Reflector.java @@ -296,6 +296,15 @@ public static boolean like(Class src, Class trg) { return isInstaneOf(src, trg, true); } + public static Object convert(Object src, Class trgClass, RefInteger rating, Object defaultValue) { + try { + return convert(src, trgClass, rating); + } + catch (PageException e) {// MUST handle this better + return defaultValue; + } + } + /** * convert Object from src to trg Type, if possible * diff --git a/core/src/main/java/lucee/runtime/reflection/pairs/ConstructorInstance.java b/core/src/main/java/lucee/runtime/reflection/pairs/ConstructorInstance.java index 512926a024..e66d55f110 100644 --- a/core/src/main/java/lucee/runtime/reflection/pairs/ConstructorInstance.java +++ b/core/src/main/java/lucee/runtime/reflection/pairs/ConstructorInstance.java @@ -18,7 +18,6 @@ **/ package lucee.runtime.reflection.pairs; -import java.io.IOException; import java.lang.reflect.InvocationTargetException; import java.util.function.BiFunction; @@ -57,8 +56,8 @@ public ConstructorInstance(Class clazz, Object[] args, boolean convertComparsion this.convertComparsion = convertComparsion; } - public Object invoke() throws PageException, InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException, NoSuchMethodException, - SecurityException, IOException { + public Object invoke() + throws PageException, InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException, NoSuchMethodException, SecurityException { try { return ((BiFunction) getResult().getValue()).apply(null, args); @@ -70,7 +69,7 @@ public Object invoke() throws PageException, InstantiationException, IllegalAcce boolean failed = false; try { DynamicInvoker di = DynamicInvoker.getExistingInstance(); - lucee.transformer.dynamic.meta.Constructor constr = Clazz.getConstructorMatch(di.getClazz(clazz, true), args, true, convertComparsion); + lucee.transformer.dynamic.meta.Constructor constr = di.getClazz(clazz, true).getConstructor(args, true, convertComparsion); return ((LegacyConstuctor) constr).getConstructor().newInstance(args); } catch (IncompatibleClassChangeError | ClassFormatError | IllegalStateException ex) { diff --git a/core/src/main/java/lucee/runtime/reflection/pairs/MethodInstance.java b/core/src/main/java/lucee/runtime/reflection/pairs/MethodInstance.java index ecfdbb32ca..be52d9be26 100644 --- a/core/src/main/java/lucee/runtime/reflection/pairs/MethodInstance.java +++ b/core/src/main/java/lucee/runtime/reflection/pairs/MethodInstance.java @@ -72,7 +72,7 @@ public Object invoke(Object o) throws PageException { LogUtil.log("dynamic", e); DynamicInvoker di = DynamicInvoker.getExistingInstance(); try { - lucee.transformer.dynamic.meta.Method method = Clazz.getMethodMatch(di.getClazz(clazz, true), methodName, args, nameCaseSensitive, true, true); + lucee.transformer.dynamic.meta.Method method = di.getClazz(clazz, true).getMethod(methodName.getString(), args, nameCaseSensitive, true, true); return ((LegacyMethod) method).getMethod().invoke(o, args); } catch (Exception e1) { @@ -98,7 +98,7 @@ public static Object invoke(Object obj, Key methodName, Object[] args, boolean n LogUtil.log("dynamic", e); DynamicInvoker di = DynamicInvoker.getExistingInstance(); try { - lucee.transformer.dynamic.meta.Method method = Clazz.getMethodMatch(di.getClazz(obj.getClass(), true), methodName, args, nameCaseSensitive, true, true); + lucee.transformer.dynamic.meta.Method method = di.getClazz(obj.getClass(), true).getMethod(methodName.getString(), args, nameCaseSensitive, true, true); return ((LegacyMethod) method).getMethod().invoke(obj, args); } catch (Exception e1) { diff --git a/core/src/main/java/lucee/transformer/dynamic/DynamicInvoker.java b/core/src/main/java/lucee/transformer/dynamic/DynamicInvoker.java index 788799cbde..d2a5ed0987 100644 --- a/core/src/main/java/lucee/transformer/dynamic/DynamicInvoker.java +++ b/core/src/main/java/lucee/transformer/dynamic/DynamicInvoker.java @@ -43,7 +43,6 @@ import lucee.commons.lang.SerializableObject; import lucee.commons.lang.SystemOut; import lucee.loader.engine.CFMLEngineFactory; -import lucee.runtime.exp.PageException; import lucee.runtime.op.Caster; import lucee.runtime.reflection.Reflector; import lucee.runtime.type.Collection.Key; @@ -135,7 +134,7 @@ private Object invoke(Object objMaybeNull, Class objClass, Key methodName, Ob catch (IncompatibleClassChangeError | IllegalStateException e) { if (log != null) log.error("dynamic", e); if (!Clazz.allowReflection()) throw e; - lucee.transformer.dynamic.meta.Method method = Clazz.getMethodMatch(getClazz(objClass, true), methodName, arguments, nameCaseSensitive, true, convertComparsion); + lucee.transformer.dynamic.meta.Method method = getClazz(objClass, true).getMethod(methodName.getString(), arguments, nameCaseSensitive, true, convertComparsion); return ((LegacyMethod) method).getMethod().invoke(objClass, arguments); } } @@ -157,7 +156,7 @@ public Clazz getClazz(Class clazz, boolean useReflection) { public Pair getInstance(Class clazz, Key methodName, Object[] arguments, boolean nameCaseSensitive, boolean convertComparsion) throws NoSuchMethodException, IOException, UnmodifiableClassException, InstantiationException, IllegalAccessException, IllegalArgumentException, - InvocationTargetException, SecurityException, PageException { + InvocationTargetException, SecurityException { // double start = SystemUtil.millis(); boolean isConstr = methodName == null; @@ -167,8 +166,9 @@ public Pair getInstance(Class clazz, Key methodName, // getClass -= start; // start = SystemUtil.millis(); // getClass += start; - lucee.transformer.dynamic.meta.FunctionMember fm = isConstr ? Clazz.getConstructorMatch(clazzz, arguments, true, convertComparsion) - : Clazz.getMethodMatch(clazzz, methodName, arguments, nameCaseSensitive, true, convertComparsion); + + lucee.transformer.dynamic.meta.FunctionMember fm = isConstr ? clazzz.getConstructor(arguments, true, convertComparsion) + : clazzz.getMethod(methodName.getString(), arguments, nameCaseSensitive, true, convertComparsion); // match -= start; // start = SystemUtil.millis(); @@ -736,7 +736,7 @@ public static void main(String[] argsw) throws Throwable { aprint.e(e.invokeInstanceMethod(new SystemOut(), "setOut", new Object[] { null }, true, true)); System.setProperty("a.b.c", "- value -"); - aprint.e(e.invokeInstanceMethod(sb, "toSTring", new Object[] {}, true, false)); + aprint.e(e.invokeInstanceMethod(sb, "toSTring", new Object[] {}, false, false)); aprint.e(e.invokeStaticMethod(SystemUtil.class, "getSystemPropOrEnvVar", new Object[] { "a.b.c", "default-value" }, true, true)); aprint.e(e.invokeStaticMethod(ListUtil.class, "arrayToList", new Object[] { new String[] { "a", "b" }, "," }, true, true)); aprint.e("done"); diff --git a/core/src/main/java/lucee/transformer/dynamic/meta/Clazz.java b/core/src/main/java/lucee/transformer/dynamic/meta/Clazz.java index fceb473814..2aff4c8cfd 100644 --- a/core/src/main/java/lucee/transformer/dynamic/meta/Clazz.java +++ b/core/src/main/java/lucee/transformer/dynamic/meta/Clazz.java @@ -16,16 +16,9 @@ import lucee.commons.lang.ClassException; import lucee.commons.lang.ClassUtil; import lucee.commons.lang.Pair; -import lucee.commons.lang.PhysicalClassLoader; import lucee.commons.lang.types.RefInteger; import lucee.commons.lang.types.RefIntegerImpl; -import lucee.runtime.config.Constants; -import lucee.runtime.exp.FunctionException; -import lucee.runtime.exp.PageException; -import lucee.runtime.java.JavaObject; import lucee.runtime.op.Caster; -import lucee.runtime.reflection.Reflector; -import lucee.runtime.type.Collection; import lucee.transformer.bytecode.util.ASMUtil; import lucee.transformer.dynamic.DynamicClassLoader; import lucee.transformer.dynamic.DynamicInvoker; @@ -33,7 +26,7 @@ import lucee.transformer.dynamic.meta.reflection.ClazzReflection; public abstract class Clazz implements Serializable { - + private static final boolean debug = false; public static final int VERSION = 4; private static final long serialVersionUID = 4236939474343760825L; @@ -53,8 +46,16 @@ public abstract class Clazz implements Serializable { public abstract Method getMethod(String methodName, Class[] arguments, boolean nameCaseSensitive) throws IOException, NoSuchMethodException; + public abstract Method getMethod(String methodName, Object[] args, boolean nameCaseSensitive, boolean convertArgument, boolean convertComparsion) throws NoSuchMethodException; + + public abstract Method getMethod(String methodName, Object[] args, boolean nameCaseSensitive, boolean convertArgument, boolean convertComparsion, Method defaultValue); + public abstract Constructor getConstructor(Class[] arguments) throws IOException, NoSuchMethodException; + public abstract Constructor getConstructor(Object[] args, boolean convertArgument, boolean convertComparsion) throws NoSuchMethodException; + + public abstract Constructor getConstructor(Object[] args, boolean convertArgument, boolean convertComparsion, Constructor defaultValue); + public abstract Constructor getDeclaredConstructor(Class[] arguments) throws IOException, NoSuchMethodException; public abstract Class getDeclaringClass(); @@ -101,244 +102,6 @@ public static Clazz getClazz(Class clazz, Resource root, Log log) { private static Map>> cachedMethods = new ConcurrentHashMap<>(); - public static Method getMethodMatch(Clazz clazz, final Collection.Key methodName, Object[] args, boolean nameCaseSensitive, boolean convertArgument, boolean convertComparsion) - throws NoSuchMethodException, IOException, PageException { - - List methods = clazz.getMethods(methodName.getString(), false, args.length); - if (methods != null && methods.size() > 0) { - if (args.length == 0) { - return methods.get(0); - } - - Class[] clazzArgs = Reflector.getClasses(args); - - Reflector.checkAccessibility(clazz, methodName); - - // like comparsion - outer: for (Method m: methods) { - if (m != null) { - Class[] parameterTypes = m.getArgumentClasses(); - for (int y = 0; y < parameterTypes.length; y++) { - if (!Reflector.toReferenceClass(parameterTypes[y]).isAssignableFrom(clazzArgs[y])) continue outer; - } - return m; - } - } - - // cache - StringBuilder sb = new StringBuilder(100).append(clazz.id()).append(methodName).append(';'); - for (Class cls: clazzArgs) { - sb.append(cls.getName()).append(';'); - } - String key = sb.toString(); - - // get match from cache - SoftReference> sr = cachedMethods.get(key); - if (sr != null) { - Pair p = sr.get(); - if (p != null) { - // print.e("used cached match(" + p.getValue() + "):" + key + ":" + cachedMethods.size()); - // convert arguments - if (p.getValue()) { - Class[] trgArgs = p.getName().getArgumentClasses(); - for (int x = 0; x < trgArgs.length; x++) { - if (args[x] != null) args[x] = Reflector.convert(args[x], Reflector.toReferenceClass(trgArgs[x]), nirvana); - } - } - return p.getName(); - } - } - - // convert comparsion - Pair result = null; - int _rating = 0; - if (convertComparsion) { - outer: for (Method m: methods) { - if (m != null) { - RefInteger rating = (methods.size() > 1) ? new RefIntegerImpl(0) : null; - Class[] parameterTypes = m.getArgumentClasses(); - Object[] newArgs = new Object[args.length]; - - for (int y = 0; y < parameterTypes.length; y++) { - try { - newArgs[y] = Reflector.convert(args[y], Reflector.toReferenceClass(parameterTypes[y]), rating); - } - catch (PageException e) { - continue outer; - } - } - if (result == null || rating.toInt() > _rating) { - if (rating != null) _rating = rating.toInt(); - result = new Pair(m, newArgs); - } - } - } - } - // convert += (SystemUtil.millis() - start); - // start = SystemUtil.millis(); - if (result != null) { - if (convertArgument) { - Object[] newArgs = result.getValue(); - for (int x = 0; x < args.length; x++) { - args[x] = newArgs[x]; - } - } - // print.e("conv match:" + key + ":"); - cachedMethods.put(key, new SoftReference>(new Pair(result.getName(), Boolean.TRUE))); - return result.getName(); - } - } - Class[] classes = Reflector.getClasses(args); - // StringBuilder sb=null; - JavaObject jo; - Class c; - Constructor cc; - for (int i = 0; i < classes.length; i++) { - if (args[i] instanceof JavaObject) { - jo = (JavaObject) args[i]; - c = jo.getClazz(); - cc = Reflector.getConstructorInstance(c, new Object[0], true).getConstructor(null); - if (cc == null) { - - throw new NoSuchMethodException( - "The " + Reflector.pos(i + 1) + " parameter of " + methodName + "(" + Reflector.getDspMethods(classes) + ") ia an object created " - + "by the createObject function (JavaObject/JavaProxy). This object has not been instantiated because it does not have a constructor " - + "that takes zero arguments. " + Constants.NAME - + " cannot instantiate it for you, please use the .init(...) method to instantiate it with the correct parameters first"); - - } - } - } - - // lclasses += (SystemUtil.millis() - start); - // start = SystemUtil.millis(); - /* - * the argument list contains objects created by createObject, that are no instantiated - * (first,third,10th) and because this object have no constructor taking no arguments, Lucee cannot - * instantiate them. you need first to instantiate this objects. - */ - - Class[] trgArgs = Reflector.getClasses(args); - String strTrgArgs = Reflector.getDspMethods(trgArgs); - StringBuilder msg = new StringBuilder(); - msg.append("No matching method for ").append(lucee.runtime.type.util.Type.getName(clazz.getDeclaringClass())).append(".").append(methodName).append("(").append(strTrgArgs) - .append(") found. "); - if (methods.size() > 0) { - msg.append("there are similar methods with the same name, but diferent arguments:\n "); - Class[] srcArgs; - String strSrcArgs; - for (Method m: methods) { - srcArgs = m.getArgumentClasses(); - strSrcArgs = Reflector.getDspMethods(srcArgs); - if (strSrcArgs.equals(strTrgArgs)) { - ClassLoader srcClassLoader = null; - ClassLoader trgClassLoader = null; - int index = -1; - for (int i = 0; i < srcArgs.length; i++) { - if (srcArgs[i].getClassLoader() == trgArgs[i].getClassLoader()) continue; - index = i; - srcClassLoader = srcArgs[i].getClassLoader(); - trgClassLoader = trgArgs[i].getClassLoader(); - break; - } - String srcClassLoaderName = "Bootstrap ClassLoader"; - if (srcClassLoader instanceof PhysicalClassLoader) { - srcClassLoaderName = "PhysicalClassLoader loaded at " + ((PhysicalClassLoader) srcClassLoader).getBirthplace(); - } - else if (srcClassLoader != null) { - srcClassLoaderName = srcClassLoader.toString(); - } - String trgClassLoaderName = "Bootstrap ClassLoader"; - if (trgClassLoader instanceof PhysicalClassLoader) { - trgClassLoaderName = "PhysicalClassLoader loaded at " + ((PhysicalClassLoader) trgClassLoader).getBirthplace(); - } - else if (trgClassLoader != null) { - trgClassLoaderName = srcClassLoader.toString(); - } - - if (index != -1) throw new NoSuchMethodException("Found a matching method for [" + lucee.runtime.type.util.Type.getName(clazz.getDeclaringClass()) + "(" - + strSrcArgs + ")], but the classes were loaded by different class loaders. \n" + "The " + FunctionException.toStringBadArgumentPosition(index + 1) - + " argument [" + lucee.runtime.type.util.Type.getName(srcArgs[index]) + "] was loaded by the class loader [" + trgClassLoaderName - + "], but the provided argument is from the class loader [" + srcClassLoaderName + "]." - + " Ensure that both classes are loaded by the same class loader to avoid conflicts."); - - } - msg.append(methodName).append('(').append(strSrcArgs).append(");\n"); - } - - } - else { - msg.append("there are no methods with this name."); - } - // lclasses2 += (SystemUtil.millis() - start); - // start = SystemUtil.millis(); - throw new NoSuchMethodException(msg.toString()); - } - - public static Constructor getConstructorMatch(Clazz clazz, Object[] args, boolean convertArgument, boolean convertComparsion) throws NoSuchMethodException, IOException { - List constructors = clazz.getConstructors(args.length); - if (constructors != null && constructors.size() > 0) { - Class[] clazzArgs = Reflector.getClasses(args); - // like comparsion - outer: for (Constructor c: constructors) { - if (c != null) { - - Class[] parameterTypes = c.getArgumentClasses(); - for (int y = 0; y < parameterTypes.length; y++) { - if (!Reflector.toReferenceClass(parameterTypes[y]).isAssignableFrom(clazzArgs[y])) continue outer; - } - return c; - } - } - - // convert comparsion - Pair result = null; - int _rating = 0; - if (convertComparsion) { - outer: for (Constructor c: constructors) { - if (c != null) { - RefInteger rating = (constructors.size() > 1) ? new RefIntegerImpl(0) : null; - Class[] parameterTypes = c.getArgumentClasses(); - Object[] newArgs = new Object[args.length]; - for (int y = 0; y < parameterTypes.length; y++) { - try { - newArgs[y] = Reflector.convert(args[y], Reflector.toReferenceClass(parameterTypes[y]), rating); - } - catch (PageException e) { - continue outer; - } - } - if (result == null || rating.toInt() > _rating) { - if (rating != null) _rating = rating.toInt(); - result = new Pair(c, newArgs); - } - // return new ConstructorInstance(constructors[i],newArgs); - } - } - } - if (result != null) { - if (convertArgument) { - Object[] newArgs = result.getValue(); - for (int x = 0; x < args.length; x++) { - args[x] = newArgs[x]; - } - } - return result.getName(); - } - - // Exception - StringBuilder msg = new StringBuilder("No matching Constructor for ").append(clazz.getDeclaringClass().getName()).append("(") - .append(Reflector.getDspMethods(Reflector.getClasses(args))).append(") found.\n").append("We have the following constructors:\n"); - for (Constructor c: constructors) { - msg.append("- (").append(Reflector.getDspMethods(c.getArgumentClasses())).append(")\n"); - } - throw new NoSuchMethodException(msg.toString()); - } - - throw new NoSuchMethodException( - "No matching Constructor for " + clazz.getDeclaringClass().getName() + "(" + Reflector.getDspMethods(Reflector.getClasses(args)) + ") found."); - } - public static String id(FunctionMember fm) { // public java.lang.String java.lang.String.toString() StringBuilder sb = new StringBuilder(); diff --git a/core/src/main/java/lucee/transformer/dynamic/meta/dynamic/ClazzDynamic.java b/core/src/main/java/lucee/transformer/dynamic/meta/dynamic/ClazzDynamic.java index d54dd4a7c4..29b4fb7171 100644 --- a/core/src/main/java/lucee/transformer/dynamic/meta/dynamic/ClazzDynamic.java +++ b/core/src/main/java/lucee/transformer/dynamic/meta/dynamic/ClazzDynamic.java @@ -31,10 +31,13 @@ import lucee.commons.io.log.Log; import lucee.commons.io.res.Resource; import lucee.commons.lang.ExceptionUtil; +import lucee.commons.lang.Pair; import lucee.commons.lang.PhysicalClassLoader; import lucee.commons.lang.types.RefInteger; import lucee.commons.lang.types.RefIntegerImpl; import lucee.runtime.converter.JavaConverter.ObjectInputStreamImpl; +import lucee.runtime.exp.PageException; +import lucee.runtime.reflection.Reflector; import lucee.runtime.thread.ThreadUtil; import lucee.transformer.bytecode.util.ASMUtil; import lucee.transformer.dynamic.meta.Clazz; @@ -311,6 +314,101 @@ public List getMethods(String methodName, boolean nameCaseSensitive, int return list; } + private static RefInteger nirvana = new RefIntegerImpl(); + private Map>> cachedMethods; + + @Override + public Method getMethod(String methodName, Object[] args, boolean nameCaseSensitive, boolean convertArgument, boolean convertComparsion) throws NoSuchMethodException { + Method method = getMethod(methodName, args, nameCaseSensitive, convertArgument, convertComparsion, null); + if (method != null) return method; + + throw new NoSuchMethodException( + "No matching method for " + clazz.getDeclaringClass().getName() + "." + methodName + "(" + Reflector.getDspMethods(Reflector.getClasses(args)) + ") found."); + } + + @Override + public Method getMethod(String methodName, Object[] args, boolean nameCaseSensitive, boolean convertArgument, boolean convertComparsion, Method defaultValue) { + // like + Class[] parameterTypes; + outer: for (Method fm: methods) { + if ((args.length == fm.getArgumentCount()) && (nameCaseSensitive ? methodName.equals(fm.getName()) : methodName.equalsIgnoreCase(fm.getName()))) { + parameterTypes = fm.getArgumentClasses(); + for (int y = 0; y < parameterTypes.length; y++) { + if (!Reflector.toReferenceClass(parameterTypes[y]).isAssignableFrom(args[y] == null ? Object.class : args[y].getClass())) continue outer; + } + return fm; + } + } + + // cache + StringBuilder sb = new StringBuilder(100).append(methodName).append(';'); // append(id()). + for (Object arg: args) { + sb.append((arg == null ? Object.class : arg.getClass()).getName()).append(';'); + } + String key = sb.toString(); + + // get match from cache + if (cachedMethods != null) { + SoftReference> sr = cachedMethods.get(key); + if (sr != null) { + Pair p = sr.get(); + if (p != null) { + // print.e("used cached match(" + p.getValue() + "):" + key + ":" + cachedMethods.size()); + // convert arguments + if (p.getValue()) { + Class[] trgArgs = p.getName().getArgumentClasses(); + for (int x = 0; x < trgArgs.length; x++) { + if (args[x] != null) { + // we can ignore a fail here, because this was done before, otherwisse it would not be in the cache + args[x] = Reflector.convert(args[x], Reflector.toReferenceClass(trgArgs[x]), nirvana, null); + } + } + } + return p.getName(); + } + } + } + + // convert comparsion + Pair result = null; + int _rating = 0; + if (convertComparsion) { + outer: for (Method fm: methods) { + if ((args.length == fm.getArgumentCount()) && ((nameCaseSensitive ? methodName.equals(fm.getName()) : methodName.equalsIgnoreCase(fm.getName())))) { + RefInteger rating = (methods.length > 1) ? new RefIntegerImpl(0) : null; + parameterTypes = fm.getArgumentClasses(); + Object[] newArgs = new Object[args.length]; + + for (int y = 0; y < parameterTypes.length; y++) { + try { + newArgs[y] = Reflector.convert(args[y], Reflector.toReferenceClass(parameterTypes[y]), rating); + } + catch (PageException e) { + continue outer; + } + } + if (result == null || rating.toInt() > _rating) { + if (rating != null) _rating = rating.toInt(); + result = new Pair(fm, newArgs); + } + } + } + } + + if (result != null) { + if (convertArgument) { + Object[] newArgs = result.getValue(); + for (int x = 0; x < args.length; x++) { + args[x] = newArgs[x]; + } + } + if (cachedMethods == null) cachedMethods = new ConcurrentHashMap<>(); + cachedMethods.put(key, new SoftReference>(new Pair(result.getName(), Boolean.TRUE))); + return result.getName(); + } + return defaultValue; + } + @Override public List getDeclaredMethods(String methodName, boolean nameCaseSensitive, int argumentLength) throws IOException { List list = new LinkedList<>(); @@ -346,6 +444,68 @@ public List getConstructors(int argumentLength) throws IOException return list; } + @Override + public Constructor getConstructor(Object[] args, boolean convertArgument, boolean convertComparsion) throws NoSuchMethodException { + Constructor constructor = getConstructor(args, convertArgument, convertComparsion, null); + if (constructor != null) return constructor; + + throw new NoSuchMethodException( + "No matching Constructor for " + clazz.getDeclaringClass().getName() + "(" + Reflector.getDspMethods(Reflector.getClasses(args)) + ") found."); + } + + @Override + public Constructor getConstructor(Object[] args, boolean convertArgument, boolean convertComparsion, Constructor defaultValue) { + + // like + Class[] parameterTypes; + outer: for (Constructor fm: constructors) { + if ((args.length == fm.getArgumentCount()) && clazz.getName().equals(fm.getDeclaringClassName())) { + parameterTypes = fm.getArgumentClasses(); + for (int y = 0; y < parameterTypes.length; y++) { + if (!Reflector.toReferenceClass(parameterTypes[y]).isAssignableFrom(args[y] == null ? Object.class : args[y].getClass())) continue outer; + } + return fm; + } + } + + // convert comparsion + Pair result = null; + int _rating = 0; + if (convertComparsion) { + outer: for (Constructor fm: constructors) { + if ((args.length == fm.getArgumentCount()) && clazz.getName().equals(fm.getDeclaringClassName())) { + RefInteger rating = (constructors.length > 1) ? new RefIntegerImpl(0) : null; + parameterTypes = fm.getArgumentClasses(); + Object[] newArgs = new Object[args.length]; + for (int y = 0; y < parameterTypes.length; y++) { + try { + newArgs[y] = Reflector.convert(args[y], Reflector.toReferenceClass(parameterTypes[y]), rating); + } + catch (PageException e) { + continue outer; + } + } + if (result == null || rating.toInt() > _rating) { + if (rating != null) _rating = rating.toInt(); + result = new Pair(fm, newArgs); + } + // return new ConstructorInstance(constructors[i],newArgs); + } + } + } + + if (result != null) { + if (convertArgument) { + Object[] newArgs = result.getValue(); + for (int x = 0; x < args.length; x++) { + args[x] = newArgs[x]; + } + } + return result.getName(); + } + return defaultValue; + } + @Override public List getDeclaredConstructors(int argumentLength) throws IOException { List list = new LinkedList<>(); diff --git a/core/src/main/java/lucee/transformer/dynamic/meta/reflection/ClazzReflection.java b/core/src/main/java/lucee/transformer/dynamic/meta/reflection/ClazzReflection.java index ede4e56ee6..41da938747 100644 --- a/core/src/main/java/lucee/transformer/dynamic/meta/reflection/ClazzReflection.java +++ b/core/src/main/java/lucee/transformer/dynamic/meta/reflection/ClazzReflection.java @@ -106,4 +106,24 @@ public Constructor getDeclaredConstructor(Class[] arguments) throws IOException, return new ConstructorReflection(clazz.getDeclaredConstructor(arguments)); } + + @Override + public Method getMethod(String methodName, Object[] args, boolean nameCaseSensitive, boolean convertArgument, boolean convertComparsion) { + throw new RuntimeException("not supported yet!"); + } + + @Override + public Method getMethod(String methodName, Object[] args, boolean nameCaseSensitive, boolean convertArgument, boolean convertComparsion, Method defaultValue) { + throw new RuntimeException("not supported yet!"); + } + + @Override + public Constructor getConstructor(Object[] args, boolean convertArgument, boolean convertComparsion) throws NoSuchMethodException { + throw new RuntimeException("not supported yet!"); + } + + @Override + public Constructor getConstructor(Object[] args, boolean convertArgument, boolean convertComparsion, Constructor defaultValue) { + throw new RuntimeException("not supported yet!"); + } } diff --git a/loader/build.xml b/loader/build.xml index 3a198ac064..afaad34cdb 100644 --- a/loader/build.xml +++ b/loader/build.xml @@ -2,7 +2,7 @@ - + diff --git a/loader/pom.xml b/loader/pom.xml index f0e14bd5bc..d3d1be7545 100644 --- a/loader/pom.xml +++ b/loader/pom.xml @@ -3,7 +3,7 @@ org.lucee lucee - 6.2.0.229-SNAPSHOT + 6.2.0.230-SNAPSHOT jar Lucee Loader Build