001package ball.lang.reflect;
002/*-
003 * ##########################################################################
004 * Utilities
005 * $Id: DefaultInterfaceMethodInvocationHandler.html 6489 2020-07-19 17:22:55Z ball $
006 * $HeadURL: svn+ssh://svn.hcf.dev/var/spool/scm/repository.svn/hcf-dev/blog/2020-07-19-java-multi-release-jars/src/main/resources/javadoc/src-html/ball/lang/reflect/DefaultInterfaceMethodInvocationHandler.html $
007 * %%
008 * Copyright (C) 2008 - 2020 Allen D. Ball
009 * %%
010 * Licensed under the Apache License, Version 2.0 (the "License");
011 * you may not use this file except in compliance with the License.
012 * You may obtain a copy of the License at
013 *
014 *      http://www.apache.org/licenses/LICENSE-2.0
015 *
016 * Unless required by applicable law or agreed to in writing, software
017 * distributed under the License is distributed on an "AS IS" BASIS,
018 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
019 * See the License for the specific language governing permissions and
020 * limitations under the License.
021 * ##########################################################################
022 */
023import java.lang.invoke.MethodHandles;
024import java.lang.reflect.Constructor;
025import java.lang.reflect.InvocationHandler;
026import java.lang.reflect.Method;
027
028import static org.apache.commons.lang3.reflect.MethodUtils.invokeMethod;
029
030/**
031 * Java 8 implementation of
032 * {@link InvocationHandler#invoke(Object,Method,Object[])} to invoke an
033 * interface default method.  Implementation detail of
034 * {@link DefaultInvocationHandler}.
035 *
036 * @author {@link.uri mailto:ball@hcf.dev Allen D. Ball}
037 * @version $Revision: 6489 $
038 */
039public interface DefaultInterfaceMethodInvocationHandler extends InvocationHandler {
040
041    /**
042     * {@inheritDoc}
043     *
044     * This method assumes {@link Method#isDefault() method.isDefault()} and
045     * will invoke {@link Method} directly.
046     *
047     * @throws  Exception       If the {@link Method} cannot be invoked.
048     */
049    @Override
050    default Object invoke(Object proxy,
051                          Method method, Object[] argv) throws Throwable {
052        Constructor<MethodHandles.Lookup> constructor =
053            MethodHandles.Lookup.class
054            .getDeclaredConstructor(Class.class);
055
056        constructor.setAccessible(true);
057
058        Class<?> declarer = method.getDeclaringClass();
059        Object result =
060            constructor.newInstance(declarer)
061            .in(declarer)
062            .unreflectSpecial(method, declarer)
063            .bindTo(proxy)
064            .invokeWithArguments(argv);
065
066        return result;
067    }
068}
069