1
2
3
4
5
6
7 package org.mule.util.scan.annotations;
8
9 import org.mule.util.scan.ClassScanner;
10
11 import java.util.ArrayList;
12 import java.util.BitSet;
13 import java.util.List;
14
15 import org.apache.commons.logging.Log;
16 import org.apache.commons.logging.LogFactory;
17 import org.objectweb.asm.AnnotationVisitor;
18 import org.objectweb.asm.FieldVisitor;
19 import org.objectweb.asm.MethodVisitor;
20 import org.objectweb.asm.commons.EmptyVisitor;
21
22
23
24
25
26
27
28
29 public class AnnotationsScanner extends EmptyVisitor implements ClassScanner
30 {
31 protected final Log log = LogFactory.getLog(getClass());
32
33 private List<AnnotationInfo> classAnnotations = new ArrayList<AnnotationInfo>();
34 private List<AnnotationInfo> fieldAnnotations = new ArrayList<AnnotationInfo>();
35 private List<AnnotationInfo> methodAnnotations = new ArrayList<AnnotationInfo>();
36 private List<AnnotationInfo> paramAnnotations = new ArrayList<AnnotationInfo>();
37
38 protected AnnotationInfo currentAnnotation;
39
40 protected static final int PROCESSING_FIELD = 1;
41 protected static final int PROCESSING_METHOD = 2;
42 protected static final int PROCESSING_CLASS = 3;
43 protected static final int PROCESSING_PARAM = 4;
44
45 protected BitSet currentlyProcessing = new BitSet(4);
46
47 private AnnotationFilter filter;
48
49 private BitSet lastProcessing = null;
50
51 private String className;
52
53 private boolean match;
54
55 public AnnotationsScanner()
56 {
57 super();
58 }
59
60 public AnnotationsScanner(AnnotationFilter filter)
61 {
62 this.filter = filter;
63 }
64
65 @Override
66 public AnnotationVisitor visitParameterAnnotation(final int parameter, final String desc, final boolean visible)
67 {
68 currentAnnotation = new AnnotationInfo();
69 currentAnnotation.setClassName(getAnnotationClassName(desc));
70 currentlyProcessing.set(PROCESSING_PARAM);
71 if (log.isDebugEnabled())
72 {
73 log.debug("Parameter Annotation: " + getAnnotationClassName(desc));
74 }
75 return this;
76 }
77
78 @Override
79 public AnnotationVisitor visitAnnotation(final String desc, final boolean visible)
80 {
81
82 if (currentlyProcessing.nextSetBit(0) < 0)
83 {
84 if(lastProcessing!=null)
85 {
86 currentlyProcessing = lastProcessing;
87 }
88 else
89 {
90 return this;
91 }
92 }
93
94 currentAnnotation = new AnnotationInfo();
95 currentAnnotation.setClassName(getAnnotationClassName(desc));
96 if (log.isDebugEnabled())
97 {
98 log.debug("Annotation: " + getAnnotationClassName(desc));
99 }
100
101 return this;
102 }
103
104
105
106
107
108 @Override
109 public void visit(final int version, final int access, final String name, final String signature, final String superName, final String[] interfaces)
110 {
111 currentlyProcessing.set(PROCESSING_CLASS);
112 className = name;
113 }
114
115
116
117
118 @Override
119 public void visit(String name, Object value)
120 {
121 if (currentAnnotation != null)
122 {
123 currentAnnotation.getParams().add(new AnnotationInfo.NameValue(name, value));
124 }
125 if (log.isDebugEnabled())
126 {
127
128 log.debug(" : " + name + "=" + value);
129 }
130 }
131
132 @Override
133 public FieldVisitor visitField(final int access, final String name, final String desc, final String signature, final Object value)
134 {
135 currentlyProcessing.set(PROCESSING_FIELD);
136 return this;
137 }
138
139 @Override
140 public MethodVisitor visitMethod(final int access, final String name, final String desc, final String signature, final String[] exceptions)
141 {
142 currentlyProcessing.set(PROCESSING_METHOD);
143 return this;
144 }
145
146
147 @Override
148 public void visitEnd()
149 {
150 if (currentAnnotation != null)
151 {
152
153 if(filter!=null && !filter.accept(currentAnnotation))
154 {
155 currentlyProcessing.clear();
156 currentAnnotation = null;
157 return;
158 }
159 if (currentlyProcessing.get(PROCESSING_CLASS))
160 {
161 classAnnotations.add(currentAnnotation);
162 match = true;
163 }
164 if (currentlyProcessing.get(PROCESSING_FIELD))
165 {
166 fieldAnnotations.add(currentAnnotation);
167 match = true;
168 }
169 else if (currentlyProcessing.get(PROCESSING_PARAM))
170 {
171 paramAnnotations.add(currentAnnotation);
172 match = true;
173 }
174 else if (currentlyProcessing.get(PROCESSING_METHOD))
175 {
176 methodAnnotations.add(currentAnnotation);
177 match = true;
178 }
179 currentAnnotation = null;
180 }
181 lastProcessing = (BitSet)currentlyProcessing.clone();
182 currentlyProcessing.clear();
183
184 }
185
186 public String getAnnotationClassName(String rawName)
187 {
188 return rawName.substring(1, rawName.length() - 1).replace('/', '.');
189 }
190
191 public List<AnnotationInfo> getClassAnnotations()
192 {
193 return classAnnotations;
194 }
195
196 public List<AnnotationInfo> getFieldAnnotations()
197 {
198 return fieldAnnotations;
199 }
200
201 public List<AnnotationInfo> getMethodAnnotations()
202 {
203 return methodAnnotations;
204 }
205
206 public List<AnnotationInfo> getParamAnnotations()
207 {
208 return paramAnnotations;
209 }
210
211 public List<AnnotationInfo> getAllAnnotations()
212 {
213 List<AnnotationInfo> list = new ArrayList<AnnotationInfo>();
214 list.addAll(classAnnotations);
215 list.addAll(fieldAnnotations);
216 list.addAll(methodAnnotations);
217 list.addAll(paramAnnotations);
218 return list;
219 }
220
221 public boolean isMatch()
222 {
223 return match;
224 }
225
226 public String getClassName()
227 {
228 return className;
229 }
230 }