|
|
|
@ -19,8 +19,10 @@ package org.springframework.security.core.annotation; |
|
|
|
import java.lang.annotation.Annotation; |
|
|
|
import java.lang.annotation.Annotation; |
|
|
|
import java.lang.reflect.AnnotatedElement; |
|
|
|
import java.lang.reflect.AnnotatedElement; |
|
|
|
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; |
|
|
|
@ -29,6 +31,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; |
|
|
|
@ -169,18 +172,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)); |
|
|
|
} |
|
|
|
} |
|
|
|
@ -212,4 +212,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; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
|