package tc.oc.commons.core.reflect; import java.lang.invoke.MethodHandle; import java.lang.invoke.MethodHandleInfo; import java.lang.invoke.MethodHandles; import java.lang.invoke.MethodType; import java.lang.reflect.Method; import java.util.stream.Stream; import javax.annotation.Nullable; /** * Convenience wrapper around some JDK invoke stuff */ public class MethodResolver { private final MethodHandles.Lookup lookup; public MethodResolver(MethodHandles.Lookup lookup) { this.lookup = lookup; } public MethodResolver(Class<?> from) { this(MethodHandleUtils.privateLookup(from)); } public MethodResolver() { this(MethodHandles.publicLookup()); } public MethodHandles.Lookup lookup() { return lookup; } public Stream<MethodHandle> methodHandles(Class<?> target) { return Methods.declaredMethodsInAncestors(target) .map(method -> { try { return lookup.unreflect(method); } catch(IllegalAccessException e) { return null; } }).filter(h -> h != null); } public MethodHandle virtualHandle(Class<?> target, String name, MethodType type) throws NoSuchMethodException, IllegalAccessException { return lookup.findVirtual(target, name, type); } public MethodHandle virtualHandle(Class<?> target, Method called) throws NoSuchMethodException, IllegalAccessException { return lookup.findVirtual(target, called.getName(), Methods.methodType(called)); } public @Nullable MethodHandle tryVirtualHandle(Class<?> target, String name, MethodType type) { try { return virtualHandle(target, name, type); } catch(NoSuchMethodException | IllegalAccessException e) { return null; } } public @Nullable MethodHandle tryVirtualHandle(Class<?> target, Method called) { return tryVirtualHandle(target, called.getName(), Methods.methodType(called)); } public MethodHandleInfo virtualInfo(Class<?> target, String name, MethodType type) throws NoSuchMethodException, IllegalAccessException { return lookup.revealDirect(virtualHandle(target, name, type)); } public MethodHandleInfo virtualInfo(Class<?> target, Method called) throws NoSuchMethodException, IllegalAccessException { return virtualInfo(target, called.getName(), Methods.methodType(called)); } public boolean hasMethod(Class<?> target, String name, MethodType type) { try { virtualInfo(target, name, type); return true; } catch(NoSuchMethodException | IllegalAccessException e) { return false; } } public boolean hasMethod(Class<?> target, Method called) { return hasMethod(target, called.getName(), Methods.methodType(called)); } }