--- a/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/MethodCall.java Wed Oct 16 09:57:23 2019 -0400
+++ b/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/MethodCall.java Wed Oct 16 10:32:08 2019 -0400
@@ -23,40 +23,131 @@
package jdk.jpackage.test;
import java.lang.reflect.Constructor;
+import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Objects;
+import java.util.Optional;
+import java.util.function.Supplier;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
import jdk.jpackage.test.Functional.ThrowingConsumer;
-import jdk.jpackage.test.Functional.ThrowingSupplier;
import jdk.jpackage.test.TestInstance.TestDesc;
class MethodCall implements ThrowingConsumer {
- MethodCall(Method method, Object... args) {
+ MethodCall(Object[] instanceCtorArgs, Method method) {
+ this.ctorArgs = Optional.ofNullable(instanceCtorArgs).orElse(
+ DEFAULT_CTOR_ARGS);
this.method = method;
- this.args = args;
+ this.methodArgs = new Object[0];
+ }
+
+ MethodCall(Object[] instanceCtorArgs, Method method, Object arg) {
+ this.ctorArgs = Optional.ofNullable(instanceCtorArgs).orElse(
+ DEFAULT_CTOR_ARGS);
+ this.method = method;
+ this.methodArgs = new Object[]{arg};
}
TestDesc createDescription() {
- return TestDesc.create(method, args);
+ var descBuilder = TestDesc.createBuilder().method(method);
+ if (methodArgs.length != 0) {
+ descBuilder.methodArgs(methodArgs);
+ }
+
+ if (ctorArgs.length != 0) {
+ descBuilder.ctorArgs(ctorArgs);
+ }
+
+ return descBuilder.get();
+ }
+
+ Method getMethod() {
+ return method;
}
- Constructor getRequiredConstructor() throws NoSuchMethodException {
- return MethodCall.getRequiredConstructor(method);
+ Object newInstance() throws NoSuchMethodException, InstantiationException,
+ IllegalAccessException, IllegalArgumentException,
+ InvocationTargetException {
+ if ((method.getModifiers() & Modifier.STATIC) != 0) {
+ return null;
+ }
+
+ Constructor ctor = findRequiredConstructor(method.getDeclaringClass(),
+ ctorArgs);
+ if (ctor.isVarArgs()) {
+ // Assume constructor doesn't have fixed, only variable parameters.
+ return ctor.newInstance(new Object[]{ctorArgs});
+ }
+
+ return ctor.newInstance(ctorArgs);
+ }
+
+ void checkRequiredConstructor() throws NoSuchMethodException {
+ if ((method.getModifiers() & Modifier.STATIC) == 0) {
+ findRequiredConstructor(method.getDeclaringClass(), ctorArgs);
+ }
}
- static Constructor getRequiredConstructor(Method method) throws
- NoSuchMethodException {
- if ((method.getModifiers() & Modifier.STATIC) == 0) {
- return method.getDeclaringClass().getConstructor();
+ private static Constructor findVarArgConstructor(Class type) {
+ return Stream.of(type.getConstructors()).filter(
+ Constructor::isVarArgs).findFirst().orElse(null);
+ }
+
+ private Constructor findRequiredConstructor(Class type, Object... ctorArgs)
+ throws NoSuchMethodException {
+
+ Supplier<NoSuchMethodException> notFoundException = () -> {
+ return new NoSuchMethodException(String.format(
+ "No public contructor in %s for %s arguments", type,
+ Arrays.deepToString(ctorArgs)));
+ };
+
+ if (Stream.of(ctorArgs).allMatch(Objects::nonNull)) {
+ // No `null` in constructor args, take easy path
+ try {
+ return type.getConstructor(Stream.of(ctorArgs).map(
+ Object::getClass).collect(Collectors.toList()).toArray(
+ Class[]::new));
+ } catch (NoSuchMethodException ex) {
+ // Failed to find ctor that can take the given arguments.
+ Constructor varArgCtor = findVarArgConstructor(type);
+ if (varArgCtor != null) {
+ // There is one with variable number of arguments. Use it.
+ return varArgCtor;
+ }
+ throw notFoundException.get();
+ }
}
- return null;
+
+ List<Constructor> ctors = Stream.of(type.getConstructors())
+ .filter(ctor -> ctor.getParameterCount() == ctorArgs.length)
+ .collect(Collectors.toList());
+
+ if (ctors.isEmpty()) {
+ // No public constructors that can handle the given arguments.
+ throw notFoundException.get();
+ }
+
+ if (ctors.size() == 1) {
+ return ctors.iterator().next();
+ }
+
+ // Revisit this tricky case when it will start bothering.
+ throw notFoundException.get();
}
@Override
public void accept(Object thiz) throws Throwable {
- method.invoke(thiz, args);
+ method.invoke(thiz, methodArgs);
}
- private final Object[] args;
+ private final Object[] methodArgs;
private final Method method;
+ private final Object[] ctorArgs;
+
+ final static Object[] DEFAULT_CTOR_ARGS = new Object[0];
}