Attempt to fix lambda error detection on JDK 9

Update `LambdaSafe` to also detect `ClassCastException` messages that
start with "module/name".

See gh-11584
This commit is contained in:
Phillip Webb 2018-01-29 23:05:38 -08:00
parent c90a5a9e9e
commit 1a2186e6ef
1 changed files with 34 additions and 2 deletions

View File

@ -16,6 +16,7 @@
package org.springframework.boot.util;
import java.lang.reflect.Method;
import java.util.Collection;
import java.util.Optional;
import java.util.function.Consumer;
@ -30,6 +31,7 @@ import org.apache.commons.logging.LogFactory;
import org.springframework.core.ResolvableType;
import org.springframework.util.Assert;
import org.springframework.util.ClassUtils;
import org.springframework.util.ReflectionUtils;
/**
* Utility that can be used to invoke lambdas in a safe way. Primarily designed to help
@ -41,6 +43,17 @@ import org.springframework.util.ClassUtils;
*/
public final class LambdaSafe {
private static final Method CLASS_GET_MODULE;
private static final Method MODULE_GET_NAME;
static {
CLASS_GET_MODULE = ReflectionUtils.findMethod(Class.class, "getModule");
MODULE_GET_NAME = (CLASS_GET_MODULE == null ? null
: ReflectionUtils.findMethod(CLASS_GET_MODULE.getReturnType(),
"getName"));
}
private LambdaSafe() {
}
@ -164,12 +177,31 @@ public final class LambdaSafe {
}
private boolean startsWithArgumentClassName(String message) {
Predicate<Object> startsWith = (argument) -> argument != null
&& message.startsWith(argument.getClass().getName());
Predicate<Object> startsWith = (argument) -> startsWithArgumentClassName(
message, argument);
return startsWith.test(this.argument)
|| Stream.of(this.additionalArguments).anyMatch(startsWith);
}
private boolean startsWithArgumentClassName(String message, Object argument) {
if (argument == null) {
return false;
}
Class<? extends Object> argumentType = argument.getClass();
if (message.startsWith(argumentType.getName())) {
return true;
}
if (CLASS_GET_MODULE != null) {
Object module = ReflectionUtils.invokeMethod(CLASS_GET_MODULE,
argumentType);
Object moduleName = ReflectionUtils.invokeMethod(MODULE_GET_NAME, module);
if (message.startsWith(moduleName + "/" + argumentType.getName())) {
return true;
}
}
return false;
}
private void logNonMachingType(C callback, ClassCastException ex) {
if (this.logger.isDebugEnabled()) {
Class<?> expectedType = ResolvableType.forClass(this.callbackType)