test/jdk/tools/jpackage/helpers/jdk/jpackage/test/MethodCall.java
branchJDK-8200758-branch
changeset 58648 3bf53ffa9ae7
parent 58416 f09bf58c1f17
equal deleted inserted replaced
58647:2c43b89b1679 58648:3bf53ffa9ae7
    21  * questions.
    21  * questions.
    22  */
    22  */
    23 package jdk.jpackage.test;
    23 package jdk.jpackage.test;
    24 
    24 
    25 import java.lang.reflect.Constructor;
    25 import java.lang.reflect.Constructor;
       
    26 import java.lang.reflect.InvocationTargetException;
    26 import java.lang.reflect.Method;
    27 import java.lang.reflect.Method;
    27 import java.lang.reflect.Modifier;
    28 import java.lang.reflect.Modifier;
       
    29 import java.util.Arrays;
       
    30 import java.util.List;
       
    31 import java.util.Objects;
       
    32 import java.util.Optional;
       
    33 import java.util.function.Supplier;
       
    34 import java.util.stream.Collectors;
       
    35 import java.util.stream.Stream;
    28 import jdk.jpackage.test.Functional.ThrowingConsumer;
    36 import jdk.jpackage.test.Functional.ThrowingConsumer;
    29 import jdk.jpackage.test.Functional.ThrowingSupplier;
       
    30 import jdk.jpackage.test.TestInstance.TestDesc;
    37 import jdk.jpackage.test.TestInstance.TestDesc;
    31 
    38 
    32 class MethodCall implements ThrowingConsumer {
    39 class MethodCall implements ThrowingConsumer {
    33 
    40 
    34     MethodCall(Method method, Object... args) {
    41     MethodCall(Object[] instanceCtorArgs, Method method) {
       
    42         this.ctorArgs = Optional.ofNullable(instanceCtorArgs).orElse(
       
    43                 DEFAULT_CTOR_ARGS);
    35         this.method = method;
    44         this.method = method;
    36         this.args = args;
    45         this.methodArgs = new Object[0];
       
    46     }
       
    47 
       
    48     MethodCall(Object[] instanceCtorArgs, Method method, Object arg) {
       
    49         this.ctorArgs = Optional.ofNullable(instanceCtorArgs).orElse(
       
    50                 DEFAULT_CTOR_ARGS);
       
    51         this.method = method;
       
    52         this.methodArgs = new Object[]{arg};
    37     }
    53     }
    38 
    54 
    39     TestDesc createDescription() {
    55     TestDesc createDescription() {
    40         return TestDesc.create(method, args);
    56         var descBuilder = TestDesc.createBuilder().method(method);
       
    57         if (methodArgs.length != 0) {
       
    58             descBuilder.methodArgs(methodArgs);
       
    59         }
       
    60 
       
    61         if (ctorArgs.length != 0) {
       
    62             descBuilder.ctorArgs(ctorArgs);
       
    63         }
       
    64 
       
    65         return descBuilder.get();
    41     }
    66     }
    42 
    67 
    43     Constructor getRequiredConstructor() throws NoSuchMethodException {
    68     Method getMethod() {
    44         return MethodCall.getRequiredConstructor(method);
    69         return method;
    45     }
    70     }
    46 
    71 
    47     static Constructor getRequiredConstructor(Method method) throws
    72     Object newInstance() throws NoSuchMethodException, InstantiationException,
    48             NoSuchMethodException {
    73             IllegalAccessException, IllegalArgumentException,
       
    74             InvocationTargetException {
       
    75         if ((method.getModifiers() & Modifier.STATIC) != 0) {
       
    76             return null;
       
    77         }
       
    78 
       
    79         Constructor ctor = findRequiredConstructor(method.getDeclaringClass(),
       
    80                 ctorArgs);
       
    81         if (ctor.isVarArgs()) {
       
    82             // Assume constructor doesn't have fixed, only variable parameters.
       
    83             return ctor.newInstance(new Object[]{ctorArgs});
       
    84         }
       
    85 
       
    86         return ctor.newInstance(ctorArgs);
       
    87     }
       
    88 
       
    89     void checkRequiredConstructor() throws NoSuchMethodException {
    49         if ((method.getModifiers() & Modifier.STATIC) == 0) {
    90         if ((method.getModifiers() & Modifier.STATIC) == 0) {
    50             return method.getDeclaringClass().getConstructor();
    91             findRequiredConstructor(method.getDeclaringClass(), ctorArgs);
    51         }
    92         }
    52         return null;
    93     }
       
    94 
       
    95     private static Constructor findVarArgConstructor(Class type) {
       
    96         return Stream.of(type.getConstructors()).filter(
       
    97                 Constructor::isVarArgs).findFirst().orElse(null);
       
    98     }
       
    99 
       
   100     private Constructor findRequiredConstructor(Class type, Object... ctorArgs)
       
   101             throws NoSuchMethodException {
       
   102 
       
   103         Supplier<NoSuchMethodException> notFoundException = () -> {
       
   104             return new NoSuchMethodException(String.format(
       
   105                     "No public contructor in %s for %s arguments", type,
       
   106                     Arrays.deepToString(ctorArgs)));
       
   107         };
       
   108 
       
   109         if (Stream.of(ctorArgs).allMatch(Objects::nonNull)) {
       
   110             // No `null` in constructor args, take easy path
       
   111             try {
       
   112                 return type.getConstructor(Stream.of(ctorArgs).map(
       
   113                         Object::getClass).collect(Collectors.toList()).toArray(
       
   114                         Class[]::new));
       
   115             } catch (NoSuchMethodException ex) {
       
   116                 // Failed to find ctor that can take the given arguments.
       
   117                 Constructor varArgCtor = findVarArgConstructor(type);
       
   118                 if (varArgCtor != null) {
       
   119                     // There is one with variable number of arguments. Use it.
       
   120                     return varArgCtor;
       
   121                 }
       
   122                 throw notFoundException.get();
       
   123             }
       
   124         }
       
   125 
       
   126         List<Constructor> ctors = Stream.of(type.getConstructors())
       
   127                 .filter(ctor -> ctor.getParameterCount() == ctorArgs.length)
       
   128                 .collect(Collectors.toList());
       
   129 
       
   130         if (ctors.isEmpty()) {
       
   131             // No public constructors that can handle the given arguments.
       
   132             throw notFoundException.get();
       
   133         }
       
   134 
       
   135         if (ctors.size() == 1) {
       
   136             return ctors.iterator().next();
       
   137         }
       
   138 
       
   139         // Revisit this tricky case when it will start bothering.
       
   140         throw notFoundException.get();
    53     }
   141     }
    54 
   142 
    55     @Override
   143     @Override
    56     public void accept(Object thiz) throws Throwable {
   144     public void accept(Object thiz) throws Throwable {
    57         method.invoke(thiz, args);
   145         method.invoke(thiz, methodArgs);
    58     }
   146     }
    59 
   147 
    60     private final Object[] args;
   148     private final Object[] methodArgs;
    61     private final Method method;
   149     private final Method method;
       
   150     private final Object[] ctorArgs;
       
   151 
       
   152     final static Object[] DEFAULT_CTOR_ARGS = new Object[0];
    62 }
   153 }