private static Function createDefaultMethodSupplier()

in archaius2-core/src/main/java/com/netflix/archaius/ConfigProxyFactory.java [436:480]


    private static <T> Function<Object[], T> createDefaultMethodSupplier(Method method, Class<T> proxyObjectType, T proxyObject) {
        final MethodHandle methodHandle;

        try {
            if (SystemUtils.IS_JAVA_1_8) {
                Constructor<MethodHandles.Lookup> constructor = MethodHandles.Lookup.class
                        .getDeclaredConstructor(Class.class, int.class);
                constructor.setAccessible(true);
                methodHandle = constructor.newInstance(proxyObjectType, MethodHandles.Lookup.PRIVATE)
                        .unreflectSpecial(method, proxyObjectType)
                        .bindTo(proxyObject);
            }
            else {
                // Java 9 onwards
                methodHandle = MethodHandles.lookup()
                        .findSpecial(proxyObjectType,
                                method.getName(),
                                MethodType.methodType(method.getReturnType(), method.getParameterTypes()),
                                proxyObjectType)
                        .bindTo(proxyObject);
            }
        } catch (ReflectiveOperationException e) {
            throw new RuntimeException("Failed to create temporary object for " + proxyObjectType.getName(), e);
        }

        return (args) -> {
            try {
                if (methodHandle.type().parameterCount() == 0) {
                    //noinspection unchecked
                    return (T) methodHandle.invokeWithArguments();
                } else if (args != null) {
                    //noinspection unchecked
                    return (T) methodHandle.invokeWithArguments(args);
                } else {
                    // This is a handle to a method WITH arguments, being called with none. This happens when toString()
                    // is trying to build a representation of a proxy that has a parameterized property AND the interface
                    // provides a default method for it. There's no good default to return here, so we'll just use null
                    return null;
                }
            } catch (Throwable e) {
                maybeWrapThenRethrow(e);
                return null; // Unreachable, but the compiler doesn't know
            }
        };
    }