Merge branch '6.4.x'
This commit is contained in:
commit
3468b7f85f
|
@ -20,8 +20,10 @@ import java.lang.annotation.Annotation;
|
||||||
import java.lang.reflect.AnnotatedElement;
|
import java.lang.reflect.AnnotatedElement;
|
||||||
import java.lang.reflect.Executable;
|
import java.lang.reflect.Executable;
|
||||||
import java.lang.reflect.Method;
|
import java.lang.reflect.Method;
|
||||||
|
import java.lang.reflect.Modifier;
|
||||||
import java.lang.reflect.Parameter;
|
import java.lang.reflect.Parameter;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
@ -30,6 +32,7 @@ import java.util.Set;
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
|
|
||||||
import org.springframework.core.MethodClassKey;
|
import org.springframework.core.MethodClassKey;
|
||||||
|
import org.springframework.core.ResolvableType;
|
||||||
import org.springframework.core.annotation.AnnotationConfigurationException;
|
import org.springframework.core.annotation.AnnotationConfigurationException;
|
||||||
import org.springframework.core.annotation.MergedAnnotation;
|
import org.springframework.core.annotation.MergedAnnotation;
|
||||||
import org.springframework.core.annotation.MergedAnnotations;
|
import org.springframework.core.annotation.MergedAnnotations;
|
||||||
|
@ -221,18 +224,15 @@ final class UniqueSecurityAnnotationScanner<A extends Annotation> extends Abstra
|
||||||
return Collections.emptyList();
|
return Collections.emptyList();
|
||||||
}
|
}
|
||||||
classesToSkip.add(targetClass);
|
classesToSkip.add(targetClass);
|
||||||
try {
|
Method methodToUse = findMethod(method, targetClass);
|
||||||
Method methodToUse = targetClass.getDeclaredMethod(method.getName(), method.getParameterTypes());
|
if (methodToUse != null) {
|
||||||
List<MergedAnnotation<A>> annotations = findDirectAnnotations(methodToUse);
|
List<MergedAnnotation<A>> annotations = findDirectAnnotations(methodToUse);
|
||||||
if (!annotations.isEmpty()) {
|
if (!annotations.isEmpty()) {
|
||||||
return annotations;
|
return annotations;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (NoSuchMethodException ex) {
|
List<MergedAnnotation<A>> annotations = new ArrayList<>(
|
||||||
// move on
|
findClosestMethodAnnotations(method, targetClass.getSuperclass(), classesToSkip));
|
||||||
}
|
|
||||||
List<MergedAnnotation<A>> annotations = new ArrayList<>();
|
|
||||||
annotations.addAll(findClosestMethodAnnotations(method, targetClass.getSuperclass(), classesToSkip));
|
|
||||||
for (Class<?> inter : targetClass.getInterfaces()) {
|
for (Class<?> inter : targetClass.getInterfaces()) {
|
||||||
annotations.addAll(findClosestMethodAnnotations(method, inter, classesToSkip));
|
annotations.addAll(findClosestMethodAnnotations(method, inter, classesToSkip));
|
||||||
}
|
}
|
||||||
|
@ -264,4 +264,52 @@ final class UniqueSecurityAnnotationScanner<A extends Annotation> extends Abstra
|
||||||
.toList();
|
.toList();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static Method findMethod(Method method, Class<?> targetClass) {
|
||||||
|
for (Method candidate : targetClass.getDeclaredMethods()) {
|
||||||
|
if (candidate == method) {
|
||||||
|
return candidate;
|
||||||
|
}
|
||||||
|
if (isOverride(method, candidate)) {
|
||||||
|
return candidate;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static boolean isOverride(Method rootMethod, Method candidateMethod) {
|
||||||
|
return (!Modifier.isPrivate(candidateMethod.getModifiers())
|
||||||
|
&& candidateMethod.getName().equals(rootMethod.getName())
|
||||||
|
&& hasSameParameterTypes(rootMethod, candidateMethod));
|
||||||
|
}
|
||||||
|
|
||||||
|
private static boolean hasSameParameterTypes(Method rootMethod, Method candidateMethod) {
|
||||||
|
if (candidateMethod.getParameterCount() != rootMethod.getParameterCount()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
Class<?>[] rootParameterTypes = rootMethod.getParameterTypes();
|
||||||
|
Class<?>[] candidateParameterTypes = candidateMethod.getParameterTypes();
|
||||||
|
if (Arrays.equals(candidateParameterTypes, rootParameterTypes)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return hasSameGenericTypeParameters(rootMethod, candidateMethod, rootParameterTypes);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static boolean hasSameGenericTypeParameters(Method rootMethod, Method candidateMethod,
|
||||||
|
Class<?>[] rootParameterTypes) {
|
||||||
|
|
||||||
|
Class<?> sourceDeclaringClass = rootMethod.getDeclaringClass();
|
||||||
|
Class<?> candidateDeclaringClass = candidateMethod.getDeclaringClass();
|
||||||
|
if (!candidateDeclaringClass.isAssignableFrom(sourceDeclaringClass)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
for (int i = 0; i < rootParameterTypes.length; i++) {
|
||||||
|
Class<?> resolvedParameterType = ResolvableType.forMethodParameter(candidateMethod, i, sourceDeclaringClass)
|
||||||
|
.resolve();
|
||||||
|
if (rootParameterTypes[i] != resolvedParameterType) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -295,6 +295,30 @@ public class UniqueSecurityAnnotationScannerTests {
|
||||||
.isThrownBy(() -> this.parameterScanner.scan(parameter));
|
.isThrownBy(() -> this.parameterScanner.scan(parameter));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// gh-16751
|
||||||
|
@Test
|
||||||
|
void scanWhenAnnotationOnParameterizedInterfaceTheLocates() throws Exception {
|
||||||
|
Method method = MyServiceImpl.class.getDeclaredMethod("get", String.class);
|
||||||
|
PreAuthorize pre = this.scanner.scan(method, method.getDeclaringClass());
|
||||||
|
assertThat(pre).isNotNull();
|
||||||
|
}
|
||||||
|
|
||||||
|
// gh-16751
|
||||||
|
@Test
|
||||||
|
void scanWhenAnnotationOnParameterizedSuperClassThenLocates() throws Exception {
|
||||||
|
Method method = MyServiceImpl.class.getDeclaredMethod("getExt", Long.class);
|
||||||
|
PreAuthorize pre = this.scanner.scan(method, method.getDeclaringClass());
|
||||||
|
assertThat(pre).isNotNull();
|
||||||
|
}
|
||||||
|
|
||||||
|
// gh-16751
|
||||||
|
@Test
|
||||||
|
void scanWhenAnnotationOnParameterizedMethodThenLocates() throws Exception {
|
||||||
|
Method method = MyServiceImpl.class.getDeclaredMethod("getExtByClass", Class.class, Long.class);
|
||||||
|
PreAuthorize pre = this.scanner.scan(method, method.getDeclaringClass());
|
||||||
|
assertThat(pre).isNotNull();
|
||||||
|
}
|
||||||
|
|
||||||
interface UserService {
|
interface UserService {
|
||||||
|
|
||||||
void add(@CustomParameterAnnotation("one") String user);
|
void add(@CustomParameterAnnotation("one") String user);
|
||||||
|
@ -681,4 +705,40 @@ public class UniqueSecurityAnnotationScannerTests {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
interface MyService<C, U> {
|
||||||
|
|
||||||
|
@PreAuthorize("thirty")
|
||||||
|
C get(U u);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
abstract static class MyServiceExt<T> implements MyService<Integer, String> {
|
||||||
|
|
||||||
|
@PreAuthorize("thirtyone")
|
||||||
|
abstract T getExt(T t);
|
||||||
|
|
||||||
|
@PreAuthorize("thirtytwo")
|
||||||
|
abstract <S extends Number> S getExtByClass(Class<S> clazz, T t);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
static class MyServiceImpl extends MyServiceExt<Long> {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Integer get(final String s) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
Long getExt(Long o) {
|
||||||
|
return 0L;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
<S extends Number> S getExtByClass(Class<S> clazz, Long l) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue