Skip to content

Commit dc514b3

Browse files
committed
FilterInvocation Support Default Methods on HttpServletRequest
Closes gh-8566
1 parent 16b0a26 commit dc514b3

File tree

1 file changed

+41
-1
lines changed

1 file changed

+41
-1
lines changed

web/src/main/java/org/springframework/security/web/FilterInvocation.java

+41-1
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,10 @@
1616

1717
package org.springframework.security.web;
1818

19+
import java.lang.invoke.MethodHandles;
20+
import java.lang.invoke.MethodHandles.Lookup;
21+
import java.lang.invoke.MethodType;
22+
import java.lang.reflect.Constructor;
1923
import java.lang.reflect.InvocationHandler;
2024
import java.lang.reflect.Method;
2125
import java.lang.reflect.Proxy;
@@ -231,7 +235,43 @@ public String getServerName() {
231235
}
232236

233237
final class UnsupportedOperationExceptionInvocationHandler implements InvocationHandler {
234-
public Object invoke(Object proxy, Method method, Object[] args) {
238+
private static final float JAVA_VERSION = Float.parseFloat(System.getProperty("java.class.version", "52"));
239+
240+
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
241+
if (method.isDefault()) {
242+
return invokeDefaultMethod(proxy, method, args);
243+
}
235244
throw new UnsupportedOperationException(method + " is not supported");
236245
}
246+
247+
private Object invokeDefaultMethod(Object proxy, Method method, Object[] args) throws Throwable {
248+
if (isJdk8OrEarlier()) {
249+
return invokeDefaultMethodForJdk8(proxy, method, args);
250+
}
251+
return MethodHandles.lookup()
252+
.findSpecial(
253+
method.getDeclaringClass(),
254+
method.getName(),
255+
MethodType.methodType(method.getReturnType(), new Class[0]),
256+
method.getDeclaringClass()
257+
)
258+
.bindTo(proxy)
259+
.invokeWithArguments(args);
260+
}
261+
262+
private Object invokeDefaultMethodForJdk8(Object proxy, Method method, Object[] args) throws Throwable {
263+
Constructor<Lookup> constructor = Lookup.class.getDeclaredConstructor(Class.class);
264+
constructor.setAccessible(true);
265+
266+
Class<?> clazz = method.getDeclaringClass();
267+
return constructor.newInstance(clazz)
268+
.in(clazz)
269+
.unreflectSpecial(method, clazz)
270+
.bindTo(proxy)
271+
.invokeWithArguments(args);
272+
}
273+
274+
private boolean isJdk8OrEarlier() {
275+
return JAVA_VERSION <= 52;
276+
}
237277
}

0 commit comments

Comments
 (0)