001package org.apache.maven.tools.plugin.extractor.annotations.scanner.visitors;
002
003/*
004 * Licensed to the Apache Software Foundation (ASF) under one
005 * or more contributor license agreements.  See the NOTICE file
006 * distributed with this work for additional information
007 * regarding copyright ownership.  The ASF licenses this file
008 * to you under the Apache License, Version 2.0 (the
009 * "License"); you may not use this file except in compliance
010 * with the License.  You may obtain a copy of the License at
011 *
012 *   http://www.apache.org/licenses/LICENSE-2.0
013 *
014 * Unless required by applicable law or agreed to in writing,
015 * software distributed under the License is distributed on an
016 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
017 * KIND, either express or implied.  See the License for the
018 * specific language governing permissions and limitations
019 * under the License.
020 */
021
022import org.apache.maven.tools.plugin.extractor.annotations.scanner.MojoAnnotatedClass;
023import org.apache.maven.tools.plugin.extractor.annotations.scanner.MojoAnnotationsScanner;
024import org.codehaus.plexus.logging.Logger;
025import org.objectweb.asm.AnnotationVisitor;
026import org.objectweb.asm.Attribute;
027import org.objectweb.asm.ClassVisitor;
028import org.objectweb.asm.FieldVisitor;
029import org.objectweb.asm.MethodVisitor;
030import org.objectweb.asm.Opcodes;
031import org.objectweb.asm.Type;
032
033import java.util.ArrayList;
034import java.util.HashMap;
035import java.util.List;
036import java.util.Map;
037import java.util.Objects;
038
039/**
040 * @author Olivier Lamy
041 * @since 3.0
042 */
043public class MojoClassVisitor
044    extends ClassVisitor
045{
046    private Logger logger;
047
048    private MojoAnnotatedClass mojoAnnotatedClass;
049
050    private Map<String, MojoAnnotationVisitor> annotationVisitorMap = new HashMap<>();
051
052    private List<MojoFieldVisitor> fieldVisitors = new ArrayList<>();
053
054    public MojoClassVisitor( Logger logger )
055    {
056        super( Opcodes.ASM9 );
057        this.logger = logger;
058    }
059
060    public MojoAnnotatedClass getMojoAnnotatedClass()
061    {
062        return mojoAnnotatedClass;
063    }
064
065    public void setMojoAnnotatedClass( MojoAnnotatedClass mojoAnnotatedClass )
066    {
067        this.mojoAnnotatedClass = mojoAnnotatedClass;
068    }
069
070    public Map<String, MojoAnnotationVisitor> getAnnotationVisitorMap()
071    {
072        return annotationVisitorMap;
073    }
074
075    public MojoAnnotationVisitor getAnnotationVisitor( Class<?> annotation )
076    {
077        return annotationVisitorMap.get( annotation.getName() );
078    }
079
080    public void setAnnotationVisitorMap( Map<String, MojoAnnotationVisitor> annotationVisitorMap )
081    {
082        this.annotationVisitorMap = annotationVisitorMap;
083    }
084
085    public List<MojoFieldVisitor> getFieldVisitors()
086    {
087        return fieldVisitors;
088    }
089
090    public void setFieldVisitors( List<MojoFieldVisitor> fieldVisitors )
091    {
092        this.fieldVisitors = fieldVisitors;
093    }
094
095    public List<MojoFieldVisitor> findFieldWithAnnotation( Class<?> annotation )
096    {
097        String annotationClassName = annotation.getName();
098
099        List<MojoFieldVisitor> mojoFieldVisitors = new ArrayList<MojoFieldVisitor>();
100
101        for ( MojoFieldVisitor mojoFieldVisitor : this.fieldVisitors )
102        {
103            MojoAnnotationVisitor mojoAnnotationVisitor = mojoFieldVisitor.getMojoAnnotationVisitor();
104            if ( mojoAnnotationVisitor != null && Objects.equals( annotationClassName,
105                                                                      mojoAnnotationVisitor.getAnnotationClassName() ) )
106            {
107                mojoFieldVisitors.add( mojoFieldVisitor );
108            }
109        }
110
111        return mojoFieldVisitors;
112    }
113
114    @Override
115    public void visit( int version, int access, String name, String signature, String superName, String[] interfaces )
116    {
117        mojoAnnotatedClass = new MojoAnnotatedClass();
118        mojoAnnotatedClass.setClassName( Type.getObjectType( name ).getClassName() );
119        if ( superName != null )
120        {
121            mojoAnnotatedClass.setParentClassName( Type.getObjectType( superName ).getClassName() );
122        }
123    }
124
125    @Override
126    public AnnotationVisitor visitAnnotation( String desc, boolean visible )
127    {
128        String annotationClassName = Type.getType( desc ).getClassName();
129        if ( !MojoAnnotationsScanner.CLASS_LEVEL_ANNOTATIONS.contains( annotationClassName ) )
130        {
131            return null;
132        }
133        MojoAnnotationVisitor mojoAnnotationVisitor = new MojoAnnotationVisitor( logger, annotationClassName );
134        annotationVisitorMap.put( annotationClassName, mojoAnnotationVisitor );
135        return mojoAnnotationVisitor;
136    }
137
138    @Override
139    public FieldVisitor visitField( int access, String name, String desc, String signature, Object value )
140    {
141        MojoFieldVisitor mojoFieldVisitor = new MojoFieldVisitor( logger, name, Type.getType( desc ).getClassName() );
142        fieldVisitors.add( mojoFieldVisitor );
143        return mojoFieldVisitor;
144    }
145
146    @Override
147    public MethodVisitor visitMethod( int access, String name, String desc, String signature, String[] exceptions )
148    {
149        // we don't need methods informations
150        return null;
151    }
152
153    @Override
154    public void visitAttribute( Attribute attr )
155    {
156        // no op
157    }
158
159    @Override
160    public void visitSource( String source, String debug )
161    {
162        // no op
163    }
164
165    @Override
166    public void visitOuterClass( String owner, String name, String desc )
167    {
168        // no op
169    }
170
171    @Override
172    public void visitInnerClass( String name, String outerName, String innerName, int access )
173    {
174        // no op
175    }
176
177    @Override
178    public void visitEnd()
179    {
180        // no op
181    }
182
183}