001/*
002 * Copyright 2002-2020 the original author or authors.
003 *
004 * Licensed under the Apache License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 *      https://www.apache.org/licenses/LICENSE-2.0
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 * See the License for the specific language governing permissions and
014 * limitations under the License.
015 */
016
017package org.springframework.core.type.classreading;
018
019import java.util.LinkedHashMap;
020import java.util.List;
021import java.util.Map;
022import java.util.Set;
023
024import org.springframework.asm.AnnotationVisitor;
025import org.springframework.asm.MethodVisitor;
026import org.springframework.asm.Opcodes;
027import org.springframework.asm.SpringAsmInfo;
028import org.springframework.asm.Type;
029import org.springframework.core.annotation.AnnotationAttributes;
030import org.springframework.core.annotation.MergedAnnotations;
031import org.springframework.core.type.MethodMetadata;
032import org.springframework.lang.Nullable;
033import org.springframework.util.LinkedMultiValueMap;
034import org.springframework.util.MultiValueMap;
035
036/**
037 * ASM method visitor which looks for the annotations defined on a method,
038 * exposing them through the {@link org.springframework.core.type.MethodMetadata}
039 * interface.
040 *
041 * @author Juergen Hoeller
042 * @author Mark Pollack
043 * @author Costin Leau
044 * @author Chris Beams
045 * @author Phillip Webb
046 * @since 3.0
047 * @deprecated As of Spring Framework 5.2, this class and related classes in this
048 * package have been replaced by {@link SimpleAnnotationMetadataReadingVisitor}
049 * and related classes for internal use within the framework.
050 */
051@Deprecated
052public class MethodMetadataReadingVisitor extends MethodVisitor implements MethodMetadata {
053
054        protected final String methodName;
055
056        protected final int access;
057
058        protected final String declaringClassName;
059
060        protected final String returnTypeName;
061
062        @Nullable
063        protected final ClassLoader classLoader;
064
065        protected final Set<MethodMetadata> methodMetadataSet;
066
067        protected final Map<String, Set<String>> metaAnnotationMap = new LinkedHashMap<>(4);
068
069        protected final LinkedMultiValueMap<String, AnnotationAttributes> attributesMap = new LinkedMultiValueMap<>(4);
070
071
072        public MethodMetadataReadingVisitor(String methodName, int access, String declaringClassName,
073                        String returnTypeName, @Nullable ClassLoader classLoader, Set<MethodMetadata> methodMetadataSet) {
074
075                super(SpringAsmInfo.ASM_VERSION);
076                this.methodName = methodName;
077                this.access = access;
078                this.declaringClassName = declaringClassName;
079                this.returnTypeName = returnTypeName;
080                this.classLoader = classLoader;
081                this.methodMetadataSet = methodMetadataSet;
082        }
083
084
085        @Override
086        public MergedAnnotations getAnnotations() {
087                throw new UnsupportedOperationException();
088        }
089
090        @Override
091        @Nullable
092        public AnnotationVisitor visitAnnotation(final String desc, boolean visible) {
093                if (!visible) {
094                        return null;
095                }
096                this.methodMetadataSet.add(this);
097                String className = Type.getType(desc).getClassName();
098                return new AnnotationAttributesReadingVisitor(
099                                className, this.attributesMap, this.metaAnnotationMap, this.classLoader);
100        }
101
102
103        @Override
104        public String getMethodName() {
105                return this.methodName;
106        }
107
108        @Override
109        public boolean isAbstract() {
110                return ((this.access & Opcodes.ACC_ABSTRACT) != 0);
111        }
112
113        @Override
114        public boolean isStatic() {
115                return ((this.access & Opcodes.ACC_STATIC) != 0);
116        }
117
118        @Override
119        public boolean isFinal() {
120                return ((this.access & Opcodes.ACC_FINAL) != 0);
121        }
122
123        @Override
124        public boolean isOverridable() {
125                return (!isStatic() && !isFinal() && ((this.access & Opcodes.ACC_PRIVATE) == 0));
126        }
127
128        @Override
129        public boolean isAnnotated(String annotationName) {
130                return this.attributesMap.containsKey(annotationName);
131        }
132
133        @Override
134        @Nullable
135        public AnnotationAttributes getAnnotationAttributes(String annotationName, boolean classValuesAsString) {
136                AnnotationAttributes raw = AnnotationReadingVisitorUtils.getMergedAnnotationAttributes(
137                                this.attributesMap, this.metaAnnotationMap, annotationName);
138                if (raw == null) {
139                        return null;
140                }
141                return AnnotationReadingVisitorUtils.convertClassValues(
142                                "method '" + getMethodName() + "'", this.classLoader, raw, classValuesAsString);
143        }
144
145        @Override
146        @Nullable
147        public MultiValueMap<String, Object> getAllAnnotationAttributes(String annotationName, boolean classValuesAsString) {
148                if (!this.attributesMap.containsKey(annotationName)) {
149                        return null;
150                }
151                MultiValueMap<String, Object> allAttributes = new LinkedMultiValueMap<>();
152                List<AnnotationAttributes> attributesList = this.attributesMap.get(annotationName);
153                if (attributesList != null) {
154                        String annotatedElement = "method '" + getMethodName() + '\'';
155                        for (AnnotationAttributes annotationAttributes : attributesList) {
156                                AnnotationAttributes convertedAttributes = AnnotationReadingVisitorUtils.convertClassValues(
157                                                annotatedElement, this.classLoader, annotationAttributes, classValuesAsString);
158                                convertedAttributes.forEach(allAttributes::add);
159                        }
160                }
161                return allAttributes;
162        }
163
164        @Override
165        public String getDeclaringClassName() {
166                return this.declaringClassName;
167        }
168
169        @Override
170        public String getReturnTypeName() {
171                return this.returnTypeName;
172        }
173
174}