1 package org.apache.onami.autobind.scanner.asm;
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 import static java.util.Collections.unmodifiableList;
21 import static java.util.logging.Level.WARNING;
22 import static java.util.logging.Logger.getLogger;
23 import static org.objectweb.asm.ClassReader.SKIP_CODE;
24 import static org.objectweb.asm.ClassReader.SKIP_DEBUG;
25 import static org.objectweb.asm.ClassReader.SKIP_FRAMES;
26 import static org.objectweb.asm.Opcodes.ASM4;
27
28 import java.lang.annotation.Annotation;
29 import java.util.HashMap;
30 import java.util.LinkedList;
31 import java.util.List;
32 import java.util.Map;
33 import java.util.logging.Logger;
34
35 import org.apache.onami.autobind.scanner.features.ScannerFeature;
36 import org.objectweb.asm.AnnotationVisitor;
37 import org.objectweb.asm.ClassVisitor;
38
39
40
41
42 final class AnnotationCollector
43 extends ClassVisitor
44 {
45
46 public static final int ASM_FLAGS = SKIP_CODE | SKIP_DEBUG | SKIP_FRAMES;
47
48 private final Logger _logger = getLogger( getClass().getName() );
49
50 private String _name;
51
52 private Class<?> _class;
53
54 private boolean _ignore;
55
56 private final Map<String, Annotation> _annotations;
57
58 private final List<ScannerFeature> _features;
59
60 public AnnotationCollector()
61 {
62 super( ASM4 );
63 _features = new LinkedList<ScannerFeature>();
64 _annotations = new HashMap<String, Annotation>();
65 }
66
67 public void addScannerFeature( ScannerFeature listener )
68 {
69 _features.add( listener );
70 }
71
72 public void removerScannerFeature( ScannerFeature listener )
73 {
74 _features.remove( listener );
75 }
76
77 public List<ScannerFeature> getScannerFeatures()
78 {
79 return unmodifiableList( _features );
80 }
81
82 public void destroy()
83 {
84 _annotations.clear();
85 _class = null;
86 _features.clear();
87 }
88
89 @Override
90 public void visit( int version, int access, String name, String signature, String superName, String[] interfaces )
91 {
92 _name = name.replace( '/', '.' );
93 for ( String interf : interfaces )
94 {
95 if ( interf.equals( "java/lang/annotation/Annotation" ) )
96 {
97 _ignore = true;
98 return;
99 }
100 }
101 }
102
103 @SuppressWarnings( "unchecked" )
104 public AnnotationVisitor visitAnnotation( String sig, boolean visible )
105 {
106 if ( _ignore )
107 {
108 return null;
109 }
110 String annotationClassStr = sig.replace( '/', '.' ).substring( 1, sig.length() - 1 );
111 if ( _class == null )
112 {
113 try
114 {
115 _class = Thread.currentThread().getContextClassLoader().loadClass( _name );
116 }
117 catch ( ClassNotFoundException e )
118 {
119 _logger.log( WARNING, "Failure while visitAnnotation. Class could not be loaded.", e );
120 return null;
121 }
122 }
123 try
124 {
125 Class<Annotation> annotationClass =
126 (Class<Annotation>) getClass().getClassLoader().loadClass( annotationClassStr );
127 Annotation annotation = _class.getAnnotation( annotationClass );
128 _annotations.put( annotationClassStr, annotation );
129 }
130 catch ( ClassNotFoundException e )
131 {
132 e.printStackTrace();
133 _logger.log( WARNING, "Failure while visitAnnotation. Class could not be loaded.", e );
134 }
135
136 return null;
137 }
138
139 @SuppressWarnings( "unchecked" )
140 @Override
141 public void visitEnd()
142 {
143 if ( !_ignore && _annotations.size() > 0 && !_annotations.containsKey( "javax.enterprise.inject.Alternative" ) )
144 {
145 for ( ScannerFeature listener : _features )
146 {
147 listener.found( (Class<Object>) _class, _annotations );
148 }
149 }
150 _name = null;
151 _class = null;
152 _ignore = false;
153 _annotations.clear();
154 }
155
156 }