001package ball.lang.reflect;
002/*-
003 * ##########################################################################
004 * Utilities
005 * $Id: DefaultInterfaceMethodInvocationHandler.java 7215 2021-01-03 18:39:51Z ball $
006 * $HeadURL: svn+ssh://svn.hcf.dev/var/spool/scm/repository.svn/ball-util/trunk/src/main/java/ball/lang/reflect/DefaultInterfaceMethodInvocationHandler.java $
007 * %%
008 * Copyright (C) 2008 - 2021 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: 7215 $
038 */
039public interface DefaultInterfaceMethodInvocationHandler extends InvocationHandler {
040
041    /**
042     * This method assumes {@link Method#isDefault() method.isDefault()} and
043     * will invoke {@link Method} directly.
044     *
045     * @param   proxy           The proxy instance.
046     * @param   method          The {@link Method}.
047     * @param   argv            The argument array.
048     *
049     * @return  The value to return from the {@link Method} invocation.
050     *
051     * @throws  Exception       If the {@link Method} cannot be invoked.
052     */
053    @Override
054    default Object invoke(Object proxy, Method method, Object[] argv) throws Throwable {
055        Constructor<MethodHandles.Lookup> constructor =
056            MethodHandles.Lookup.class
057            .getDeclaredConstructor(Class.class);
058
059        constructor.setAccessible(true);
060
061        Class<?> declarer = method.getDeclaringClass();
062        Object result =
063            constructor.newInstance(declarer)
064            .in(declarer)
065            .unreflectSpecial(method, declarer)
066            .bindTo(proxy)
067            .invokeWithArguments(argv);
068
069        return result;
070    }
071}
072