Skip to content

Commit 9e9be81

Browse files
committed
Introduce local copies of removed Spring Framework API for ASM metadata parsing.
Should be removed after revisiting our design. See #2498
1 parent 34568d0 commit 9e9be81

9 files changed

+1119
-2
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
/*
2+
* Copyright 2021 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package org.springframework.data.type.classreading;
17+
18+
import java.lang.reflect.Field;
19+
import java.security.AccessControlException;
20+
21+
import org.apache.commons.logging.Log;
22+
import org.apache.commons.logging.LogFactory;
23+
24+
import org.springframework.asm.AnnotationVisitor;
25+
import org.springframework.asm.SpringAsmInfo;
26+
import org.springframework.asm.Type;
27+
import org.springframework.core.annotation.AnnotationAttributes;
28+
import org.springframework.core.type.classreading.SimpleAnnotationMetadataReadingVisitor;
29+
import org.springframework.lang.Nullable;
30+
import org.springframework.util.ClassUtils;
31+
import org.springframework.util.ReflectionUtils;
32+
33+
/**
34+
* {@link AnnotationVisitor} to recursively visit annotations.
35+
*
36+
* @author Chris Beams
37+
* @author Juergen Hoeller
38+
* @author Phillip Webb
39+
* @author Sam Brannen
40+
* @since 3.1.1
41+
* @deprecated As of Spring Framework 5.2, this class and related classes in this package have been replaced by
42+
* {@link SimpleAnnotationMetadataReadingVisitor} and related classes for internal use within the framework.
43+
*/
44+
@Deprecated
45+
abstract class AbstractRecursiveAnnotationVisitor extends AnnotationVisitor {
46+
47+
protected final Log logger = LogFactory.getLog(getClass());
48+
49+
protected final AnnotationAttributes attributes;
50+
51+
@Nullable protected final ClassLoader classLoader;
52+
53+
public AbstractRecursiveAnnotationVisitor(@Nullable ClassLoader classLoader, AnnotationAttributes attributes) {
54+
super(SpringAsmInfo.ASM_VERSION);
55+
this.classLoader = classLoader;
56+
this.attributes = attributes;
57+
}
58+
59+
@Override
60+
public void visit(String attributeName, Object attributeValue) {
61+
this.attributes.put(attributeName, attributeValue);
62+
}
63+
64+
@Override
65+
public AnnotationVisitor visitAnnotation(String attributeName, String asmTypeDescriptor) {
66+
String annotationType = Type.getType(asmTypeDescriptor).getClassName();
67+
AnnotationAttributes nestedAttributes = new AnnotationAttributes(annotationType, this.classLoader);
68+
this.attributes.put(attributeName, nestedAttributes);
69+
return new RecursiveAnnotationAttributesVisitor(annotationType, nestedAttributes, this.classLoader);
70+
}
71+
72+
@Override
73+
public AnnotationVisitor visitArray(String attributeName) {
74+
return new RecursiveAnnotationArrayVisitor(attributeName, this.attributes, this.classLoader);
75+
}
76+
77+
@Override
78+
public void visitEnum(String attributeName, String asmTypeDescriptor, String attributeValue) {
79+
Object newValue = getEnumValue(asmTypeDescriptor, attributeValue);
80+
visit(attributeName, newValue);
81+
}
82+
83+
protected Object getEnumValue(String asmTypeDescriptor, String attributeValue) {
84+
Object valueToUse = attributeValue;
85+
try {
86+
Class<?> enumType = ClassUtils.forName(Type.getType(asmTypeDescriptor).getClassName(), this.classLoader);
87+
Field enumConstant = ReflectionUtils.findField(enumType, attributeValue);
88+
if (enumConstant != null) {
89+
ReflectionUtils.makeAccessible(enumConstant);
90+
valueToUse = enumConstant.get(null);
91+
}
92+
} catch (ClassNotFoundException | NoClassDefFoundError ex) {
93+
logger.debug("Failed to classload enum type while reading annotation metadata", ex);
94+
} catch (IllegalAccessException | AccessControlException ex) {
95+
logger.debug("Could not access enum value while reading annotation metadata", ex);
96+
}
97+
return valueToUse;
98+
}
99+
100+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,120 @@
1+
/*
2+
* Copyright 2021 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package org.springframework.data.type.classreading;
17+
18+
import java.lang.annotation.Annotation;
19+
import java.lang.reflect.Modifier;
20+
import java.util.LinkedHashSet;
21+
import java.util.List;
22+
import java.util.Map;
23+
import java.util.Set;
24+
25+
import org.springframework.core.annotation.AnnotationAttributes;
26+
import org.springframework.core.annotation.AnnotationUtils;
27+
import org.springframework.core.type.classreading.SimpleAnnotationMetadataReadingVisitor;
28+
import org.springframework.lang.Nullable;
29+
import org.springframework.util.MultiValueMap;
30+
import org.springframework.util.ObjectUtils;
31+
32+
/**
33+
* ASM visitor which looks for annotations defined on a class or method, including meta-annotations.
34+
* <p>
35+
* This visitor is fully recursive, taking into account any nested annotations or nested annotation arrays.
36+
*
37+
* @author Juergen Hoeller
38+
* @author Chris Beams
39+
* @author Phillip Webb
40+
* @author Sam Brannen
41+
* @since 3.0
42+
* @deprecated As of Spring Framework 5.2, this class and related classes in this package have been replaced by
43+
* {@link SimpleAnnotationMetadataReadingVisitor} and related classes for internal use within the framework.
44+
*/
45+
@Deprecated
46+
final class AnnotationAttributesReadingVisitor extends RecursiveAnnotationAttributesVisitor {
47+
48+
private final MultiValueMap<String, AnnotationAttributes> attributesMap;
49+
50+
private final Map<String, Set<String>> metaAnnotationMap;
51+
52+
public AnnotationAttributesReadingVisitor(String annotationType,
53+
MultiValueMap<String, AnnotationAttributes> attributesMap, Map<String, Set<String>> metaAnnotationMap,
54+
@Nullable ClassLoader classLoader) {
55+
56+
super(annotationType, new AnnotationAttributes(annotationType, classLoader), classLoader);
57+
this.attributesMap = attributesMap;
58+
this.metaAnnotationMap = metaAnnotationMap;
59+
}
60+
61+
@Override
62+
public void visitEnd() {
63+
super.visitEnd();
64+
65+
Class<? extends Annotation> annotationClass = this.attributes.annotationType();
66+
if (annotationClass != null) {
67+
List<AnnotationAttributes> attributeList = this.attributesMap.get(this.annotationType);
68+
if (attributeList == null) {
69+
this.attributesMap.add(this.annotationType, this.attributes);
70+
} else {
71+
attributeList.add(0, this.attributes);
72+
}
73+
if (!AnnotationUtils.isInJavaLangAnnotationPackage(annotationClass.getName())) {
74+
try {
75+
Annotation[] metaAnnotations = annotationClass.getAnnotations();
76+
if (!ObjectUtils.isEmpty(metaAnnotations)) {
77+
Set<Annotation> visited = new LinkedHashSet<>();
78+
for (Annotation metaAnnotation : metaAnnotations) {
79+
recursivelyCollectMetaAnnotations(visited, metaAnnotation);
80+
}
81+
if (!visited.isEmpty()) {
82+
Set<String> metaAnnotationTypeNames = new LinkedHashSet<>(visited.size());
83+
for (Annotation ann : visited) {
84+
metaAnnotationTypeNames.add(ann.annotationType().getName());
85+
}
86+
this.metaAnnotationMap.put(annotationClass.getName(), metaAnnotationTypeNames);
87+
}
88+
}
89+
} catch (Throwable ex) {
90+
if (logger.isDebugEnabled()) {
91+
logger.debug("Failed to introspect meta-annotations on " + annotationClass + ": " + ex);
92+
}
93+
}
94+
}
95+
}
96+
}
97+
98+
private void recursivelyCollectMetaAnnotations(Set<Annotation> visited, Annotation annotation) {
99+
Class<? extends Annotation> annotationType = annotation.annotationType();
100+
String annotationName = annotationType.getName();
101+
if (!AnnotationUtils.isInJavaLangAnnotationPackage(annotationName) && visited.add(annotation)) {
102+
try {
103+
// Only do attribute scanning for public annotations; we'd run into
104+
// IllegalAccessExceptions otherwise, and we don't want to mess with
105+
// accessibility in a SecurityManager environment.
106+
if (Modifier.isPublic(annotationType.getModifiers())) {
107+
this.attributesMap.add(annotationName, AnnotationUtils.getAnnotationAttributes(annotation, false, true));
108+
}
109+
for (Annotation metaMetaAnnotation : annotationType.getAnnotations()) {
110+
recursivelyCollectMetaAnnotations(visited, metaMetaAnnotation);
111+
}
112+
} catch (Throwable ex) {
113+
if (logger.isDebugEnabled()) {
114+
logger.debug("Failed to introspect meta-annotations on " + annotation + ": " + ex);
115+
}
116+
}
117+
}
118+
}
119+
120+
}

0 commit comments

Comments
 (0)