001    /*
002     * Licensed under the Apache License, Version 2.0 (the "License");
003     * you may not use this file except in compliance with the License.
004     * You may obtain a copy of the License at
005     *
006     *      http://www.apache.org/licenses/LICENSE-2.0
007     *
008     * Unless required by applicable law or agreed to in writing, software
009     * distributed under the License is distributed on an "AS IS" BASIS,
010     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
011     * See the License for the specific language governing permissions and
012     * limitations under the License.
013     */
014    package org.apache.commons.classscan.bcel;
015    
016    import java.util.Set;
017    
018    import org.apache.bcel.classfile.Method;
019    import org.apache.bcel.classfile.ParameterAnnotationEntry;
020    import org.apache.bcel.generic.Type;
021    import org.apache.commons.classscan.model.MetaAnnotation;
022    import org.apache.commons.classscan.model.MetaParameter;
023    import org.apache.commons.classscan.model.MetaType;
024    import org.apache.commons.classscan.spi.model.SpiMetaClassLoader;
025    import org.apache.commons.classscan.spi.model.SpiMetaMethod;
026    import org.apache.commons.classscan.spi.model.SpiMetaParameter;
027    import org.apache.commons.classscan.util.ResolveSet;
028    
029    public class BcelMethod implements SpiMetaMethod {
030    
031        private final String methodName;
032        private final boolean isStatic;
033        private final AnnotationMap annotations;
034        private MetaType returnType;
035        private String returnTypeDescriptor;
036        private final ResolveSet<SpiMetaParameter> paramTypes;
037    
038        public BcelMethod(Method method) {
039            methodName = method.getName();
040            isStatic = method.isStatic();
041            annotations = AnnotationMap.createAnnotations(method.getAnnotationEntries());
042            returnTypeDescriptor = method.getReturnType().getSignature();
043            paramTypes = createParameters(method);
044        }
045    
046            @Override
047            public boolean resolve(SpiMetaClassLoader classLoader) {
048                    returnType = classLoader.resolveTypeForDescriptor(returnTypeDescriptor);
049                    if(returnType==null) {
050                            return false;
051                    }
052                    returnTypeDescriptor = null;
053                    
054                    return annotations.resolve(classLoader)
055                                    && paramTypes.resolve(classLoader);
056            }
057    
058        @Override
059        public String getName() {
060            return methodName;
061        }
062    
063        @Override
064        public Set<? extends MetaAnnotation> getAnnotations() {
065            return annotations;
066        }
067    
068        @Override
069        public MetaAnnotation getAnnotation(String annotationName) {
070            return annotations.getValue(annotationName);
071        }
072    
073        @Override
074        public boolean isStatic() {
075            return isStatic;
076        }
077    
078        @Override
079        public MetaType getType() {
080            return returnType;
081        }
082    
083        @Override
084        public Set<? extends MetaParameter> getParameters() {
085            return paramTypes;
086        }
087    
088        private ResolveSet<SpiMetaParameter> createParameters(Method method) {
089            final Type[] types = method.getArgumentTypes();
090            if (types.length == 0) {
091                return ResolveSet.emptyResolveSet();
092            }
093    
094            final ParameterAnnotationEntry[] parameterAnnotations = method.getParameterAnnotationEntries();
095            SpiMetaParameter[] metaParameterArray = new SpiMetaParameter[types.length];
096            for (int i = 0; i < metaParameterArray.length; ++i) {
097                // there may be less annotations than parameters
098                ParameterAnnotationEntry arg = i < parameterAnnotations.length ? parameterAnnotations[i] : null;
099                metaParameterArray[i] = new BcelParameter(types[i], arg);
100            }
101    
102            ResolveSet<SpiMetaParameter> parameters = new ResolveSet<SpiMetaParameter>(metaParameterArray);
103            return parameters;
104        }
105    }