Commit 1a2186e6 authored by Phillip Webb's avatar Phillip Webb

Attempt to fix lambda error detection on JDK 9

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

See gh-11584
parent c90a5a9e
...@@ -16,6 +16,7 @@ ...@@ -16,6 +16,7 @@
package org.springframework.boot.util; package org.springframework.boot.util;
import java.lang.reflect.Method;
import java.util.Collection; import java.util.Collection;
import java.util.Optional; import java.util.Optional;
import java.util.function.Consumer; import java.util.function.Consumer;
...@@ -30,6 +31,7 @@ import org.apache.commons.logging.LogFactory; ...@@ -30,6 +31,7 @@ import org.apache.commons.logging.LogFactory;
import org.springframework.core.ResolvableType; import org.springframework.core.ResolvableType;
import org.springframework.util.Assert; import org.springframework.util.Assert;
import org.springframework.util.ClassUtils; 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 * 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; ...@@ -41,6 +43,17 @@ import org.springframework.util.ClassUtils;
*/ */
public final class LambdaSafe { 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() { private LambdaSafe() {
} }
...@@ -164,12 +177,31 @@ public final class LambdaSafe { ...@@ -164,12 +177,31 @@ public final class LambdaSafe {
} }
private boolean startsWithArgumentClassName(String message) { private boolean startsWithArgumentClassName(String message) {
Predicate<Object> startsWith = (argument) -> argument != null Predicate<Object> startsWith = (argument) -> startsWithArgumentClassName(
&& message.startsWith(argument.getClass().getName()); message, argument);
return startsWith.test(this.argument) return startsWith.test(this.argument)
|| Stream.of(this.additionalArguments).anyMatch(startsWith); || 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) { private void logNonMachingType(C callback, ClassCastException ex) {
if (this.logger.isDebugEnabled()) { if (this.logger.isDebugEnabled()) {
Class<?> expectedType = ResolvableType.forClass(this.callbackType) Class<?> expectedType = ResolvableType.forClass(this.callbackType)
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment