FilterInvocation Support Default Methods on HttpServletRequest

Closes gh-8566
This commit is contained in:
Rob Winch 2020-05-20 10:13:59 -05:00
parent 16b0a268d9
commit dc514b369e
1 changed files with 41 additions and 1 deletions

View File

@ -16,6 +16,10 @@
package org.springframework.security.web;
import java.lang.invoke.MethodHandles;
import java.lang.invoke.MethodHandles.Lookup;
import java.lang.invoke.MethodType;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
@ -231,7 +235,43 @@ class DummyRequest extends HttpServletRequestWrapper {
}
final class UnsupportedOperationExceptionInvocationHandler implements InvocationHandler {
public Object invoke(Object proxy, Method method, Object[] args) {
private static final float JAVA_VERSION = Float.parseFloat(System.getProperty("java.class.version", "52"));
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
if (method.isDefault()) {
return invokeDefaultMethod(proxy, method, args);
}
throw new UnsupportedOperationException(method + " is not supported");
}
private Object invokeDefaultMethod(Object proxy, Method method, Object[] args) throws Throwable {
if (isJdk8OrEarlier()) {
return invokeDefaultMethodForJdk8(proxy, method, args);
}
return MethodHandles.lookup()
.findSpecial(
method.getDeclaringClass(),
method.getName(),
MethodType.methodType(method.getReturnType(), new Class[0]),
method.getDeclaringClass()
)
.bindTo(proxy)
.invokeWithArguments(args);
}
private Object invokeDefaultMethodForJdk8(Object proxy, Method method, Object[] args) throws Throwable {
Constructor<Lookup> constructor = Lookup.class.getDeclaredConstructor(Class.class);
constructor.setAccessible(true);
Class<?> clazz = method.getDeclaringClass();
return constructor.newInstance(clazz)
.in(clazz)
.unreflectSpecial(method, clazz)
.bindTo(proxy)
.invokeWithArguments(args);
}
private boolean isJdk8OrEarlier() {
return JAVA_VERSION <= 52;
}
}