|
16 | 16 |
|
17 | 17 | package org.springframework.security.web;
|
18 | 18 |
|
| 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; |
19 | 23 | import java.lang.reflect.InvocationHandler;
|
20 | 24 | import java.lang.reflect.Method;
|
21 | 25 | import java.lang.reflect.Proxy;
|
@@ -231,7 +235,43 @@ public String getServerName() {
|
231 | 235 | }
|
232 | 236 |
|
233 | 237 | 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 | + } |
235 | 244 | throw new UnsupportedOperationException(method + " is not supported");
|
236 | 245 | }
|
| 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 | + } |
237 | 277 | }
|
0 commit comments