All Downloads are FREE. Search and download functionalities are using the official Maven repository.

global.maplink.helpers.ProxyHelper Maven / Gradle / Ivy

The newest version!
package global.maplink.helpers;

import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;

import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodHandles;
import java.lang.invoke.MethodType;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.*;

import static java.lang.String.format;
import static java.util.Collections.synchronizedMap;

@Slf4j
public class ProxyHelper {
    private static final MethodHandles.Lookup lookup = MethodHandles.lookup();
    private static final Map cache = synchronizedMap(new WeakHashMap<>());

    private static final List handlers = Arrays.asList(
            ProxyHelper::safeHandler,
            ProxyHelper::unsafeHandler
    );

    @SneakyThrows
    public static MethodHandle handleFor(Method method) {
        if (cache.containsKey(method)) {
            return cache.get(method);
        }
        MethodHandle result = getFromHandlers(method);
        cache.put(method, result);
        return result;
    }

    private static MethodHandle getFromHandlers(Method method) {
        List errors = new LinkedList<>();
        for (Handler h : handlers) {
            try {
                return h.handleFor(method);
            } catch (Exception e) {
                errors.add(e);
            }
        }
        Exception last = null;
        for (Exception e : errors) {
            log.warn("Error on method handler creation", e);
            last = e;
        }
        throw new IllegalArgumentException(format(
                "Cannot create handler for %s %s.%s(%s)",
                method.getReturnType(),
                method.getDeclaringClass(),
                method.getName(),
                Arrays.toString(method.getParameterTypes())
        ), last);
    }

    private static MethodHandle safeHandler(Method method) throws NoSuchMethodException, IllegalAccessException {
        MethodType methodType = MethodType.methodType(method.getReturnType(), method.getParameterTypes());
        return lookup.findSpecial(method.getDeclaringClass(), method.getName(), methodType, method.getDeclaringClass());
    }

    private static MethodHandle unsafeHandler(Method method) throws NoSuchMethodException, IllegalAccessException, InstantiationException, InvocationTargetException {
        Constructor constructor = MethodHandles.Lookup.class.getDeclaredConstructor(Class.class);
        constructor.setAccessible(true);
        return constructor.newInstance(method.getDeclaringClass())
                .in(method.getDeclaringClass())
                .unreflectSpecial(method, method.getDeclaringClass());
    }

    @FunctionalInterface
    private interface Handler {
        MethodHandle handleFor(Method method) throws Exception;
    }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy