1 package net.sf.jlayercheck.util;
2
3 import java.util.HashMap;
4 import java.util.HashSet;
5 import java.util.Map;
6 import java.util.Set;
7 import java.util.TreeSet;
8
9 import org.objectweb.asm.AnnotationVisitor;
10 import org.objectweb.asm.Attribute;
11 import org.objectweb.asm.ClassVisitor;
12 import org.objectweb.asm.FieldVisitor;
13 import org.objectweb.asm.Label;
14 import org.objectweb.asm.MethodVisitor;
15 import org.objectweb.asm.Opcodes;
16 import org.objectweb.asm.Type;
17 import org.objectweb.asm.signature.SignatureReader;
18 import org.objectweb.asm.signature.SignatureVisitor;
19
20
21
22
23
24
25 public class DependencyVisitor implements
26 AnnotationVisitor,
27 SignatureVisitor,
28 ClassVisitor,
29 FieldVisitor,
30 MethodVisitor
31 {
32 protected Map<String, Set<String>> packages = new HashMap<String, Set<String>>();
33
34 protected Map<String, Map<String, Set<Integer>>> classDependencies = new HashMap<String, Map<String, Set<Integer>>>();
35
36 protected String currentClass;
37
38 protected Map<String, Set<MethodCall>> constructorCalls = new HashMap<String, Set<MethodCall>>();
39
40
41
42
43 protected Map<String, Set<Integer>> currentClassDependencies;
44
45 protected int currentLineNumber;
46
47
48
49
50
51
52
53
54 public Map<String, Map<String, Set<Integer>>> getDependencies() {
55 return classDependencies;
56 }
57
58
59
60
61
62
63
64
65 public Map<String, Set<String>> getPackages() {
66 return packages;
67 }
68
69
70
71
72
73
74 public void visit(final int version, final int access, final String name,
75 final String signature, final String superName,
76 final String[] interfaces) {
77 currentClass = name;
78 addClassToPackage(name);
79
80 currentClassDependencies = classDependencies.get(currentClass);
81 if (currentClassDependencies == null) {
82 currentClassDependencies = new HashMap<String, Set<Integer>>();
83 classDependencies.put(currentClass, currentClassDependencies);
84 }
85 currentLineNumber = 0;
86
87
88 if (signature == null) {
89 addName(superName);
90 addNames(interfaces);
91 } else {
92 addSignature(signature);
93 }
94 }
95
96 public AnnotationVisitor visitAnnotation(
97 final String desc,
98 final boolean visible)
99 {
100 addDesc(desc);
101 return this;
102 }
103
104 public void visitAttribute(final Attribute attr) {
105 }
106
107 public FieldVisitor visitField(
108 final int access,
109 final String name,
110 final String desc,
111 final String signature,
112 final Object value)
113 {
114
115 if (signature == null) {
116 addDesc(desc);
117 } else {
118 addTypeSignature(signature);
119 }
120 if (value instanceof Type) {
121 addType((Type) value);
122 }
123 return this;
124 }
125
126 public MethodVisitor visitMethod(
127 final int access,
128 final String name,
129 final String desc,
130 final String signature,
131 final String[] exceptions)
132 {
133 if (signature == null) {
134 addMethodDesc(desc);
135 } else {
136 addSignature(signature);
137 }
138 addNames(exceptions);
139 return this;
140 }
141
142 public void visitSource(final String source, final String debug) {
143 }
144
145 public void visitInnerClass(
146 final String name,
147 final String outerName,
148 final String innerName,
149 final int access)
150 {
151
152
153 }
154
155 public void visitOuterClass(
156 final String owner,
157 final String name,
158 final String desc)
159 {
160
161
162 }
163
164
165
166 public AnnotationVisitor visitParameterAnnotation(
167 final int parameter,
168 final String desc,
169 final boolean visible)
170 {
171 addDesc(desc);
172 return this;
173 }
174
175 public void visitTypeInsn(final int opcode, final String desc) {
176
177 if (opcode == Opcodes.NEW) {
178 addConstuctorCall(desc);
179 }
180
181 if (desc.charAt(0) == '[') {
182 addDesc(desc);
183 } else {
184 addName(desc);
185 }
186 }
187
188
189
190
191
192
193
194 protected void addConstuctorCall(String desc) {
195 Set<MethodCall> methodCallList = constructorCalls.get(currentClass);
196
197 if (methodCallList == null) {
198 methodCallList = new HashSet<MethodCall>();
199 constructorCalls.put(currentClass, methodCallList);
200 }
201
202 methodCallList.add(new MethodCall(desc, null, MethodCall.Type.CONSTRUCTOR, currentLineNumber));
203
204 }
205
206 public void visitFieldInsn(
207 final int opcode,
208 final String owner,
209 final String name,
210 final String desc)
211 {
212
213 addName(owner);
214 addDesc(desc);
215 }
216
217 public void visitMethodInsn(
218 final int opcode,
219 final String owner,
220 final String name,
221 final String desc)
222 {
223
224
225 addName(owner);
226 addMethodDesc(desc);
227 }
228
229 public void visitLdcInsn(final Object cst) {
230 if (cst instanceof Type) {
231 addType((Type) cst);
232 }
233 }
234
235 public void visitMultiANewArrayInsn(final String desc, final int dims) {
236 addDesc(desc);
237 }
238
239 public void visitLocalVariable(
240 final String name,
241 final String desc,
242 final String signature,
243 final Label start,
244 final Label end,
245 final int index)
246 {
247
248 addTypeSignature(signature);
249 }
250
251 public AnnotationVisitor visitAnnotationDefault() {
252 return this;
253 }
254
255 public void visitCode() {
256 }
257
258 public void visitFrame(
259 final int type,
260 final int nLocal,
261 final Object[] local,
262 final int nStack,
263 final Object[] stack)
264 {
265 }
266
267 public void visitInsn(final int opcode) {
268 }
269
270 public void visitIntInsn(final int opcode, final int operand) {
271 }
272
273 public void visitVarInsn(final int opcode, final int var) {
274 }
275
276 public void visitJumpInsn(final int opcode, final Label label) {
277 }
278
279 public void visitLabel(final Label label) {
280 }
281
282 public void visitIincInsn(final int var, final int increment) {
283 }
284
285 public void visitTableSwitchInsn(
286 final int min,
287 final int max,
288 final Label dflt,
289 final Label[] labels)
290 {
291 }
292
293 public void visitLookupSwitchInsn(
294 final Label dflt,
295 final int[] keys,
296 final Label[] labels)
297 {
298 }
299
300 public void visitTryCatchBlock(
301 final Label start,
302 final Label end,
303 final Label handler,
304 final String type)
305 {
306 addName(type);
307 }
308
309 public void visitLineNumber(final int line, final Label start) {
310
311 currentLineNumber = line;
312 }
313
314 public void visitMaxs(final int maxStack, final int maxLocals) {
315 }
316
317
318
319 public void visit(final String name, final Object value) {
320 if (value instanceof Type) {
321 addType((Type) value);
322 }
323 }
324
325 public void visitEnum(
326 final String name,
327 final String desc,
328 final String value)
329 {
330 addDesc(desc);
331 }
332
333 public AnnotationVisitor visitAnnotation(
334 final String name,
335 final String desc)
336 {
337 addDesc(desc);
338 return this;
339 }
340
341 public AnnotationVisitor visitArray(final String name) {
342 return this;
343 }
344
345
346
347 public void visitFormalTypeParameter(final String name) {
348 }
349
350 public SignatureVisitor visitClassBound() {
351 return this;
352 }
353
354 public SignatureVisitor visitInterfaceBound() {
355 return this;
356 }
357
358 public SignatureVisitor visitSuperclass() {
359 return this;
360 }
361
362 public SignatureVisitor visitInterface() {
363 return this;
364 }
365
366 public SignatureVisitor visitParameterType() {
367 return this;
368 }
369
370 public SignatureVisitor visitReturnType() {
371 return this;
372 }
373
374 public SignatureVisitor visitExceptionType() {
375 return this;
376 }
377
378 public void visitBaseType(final char descriptor) {
379 }
380
381 public void visitTypeVariable(final String name) {
382
383
384 }
385
386 public SignatureVisitor visitArrayType() {
387 return this;
388 }
389
390 public void visitClassType(final String name) {
391
392 addName(name);
393 }
394
395 public void visitInnerClassType(final String name) {
396 addName(name);
397 }
398
399 public void visitTypeArgument() {
400 }
401
402 public SignatureVisitor visitTypeArgument(final char wildcard) {
403 return this;
404 }
405
406
407
408 public void visitEnd() {
409 }
410
411
412
413 protected void addClassToPackage(String classname) {
414
415 String packagename = StringUtils.getPackageName(classname);
416
417
418 addClassToPackage(classname, packagename);
419 }
420
421 protected void addClassToPackage(String classname, String packagename) {
422 Set<String> packageclasses = packages.get(packagename);
423 if (packageclasses == null) {
424 packageclasses = new TreeSet<String>();
425 packages.put(packagename, packageclasses);
426 }
427 packageclasses.add(classname);
428 }
429
430 protected void addName(final String name) {
431 if (name == null) {
432 return;
433 }
434
435 addClassToPackage(name);
436
437 if (!currentClassDependencies.containsKey(name)) {
438 currentClassDependencies.put(name, new TreeSet<Integer>());
439 }
440
441 currentClassDependencies.get(name).add(currentLineNumber);
442 }
443
444 protected void addNames(final String[] names) {
445 for (int i = 0; names != null && i < names.length; i++) {
446 addName(names[i]);
447 }
448 }
449
450 protected void addDesc(final String desc) {
451 addType(Type.getType(desc));
452 }
453
454 protected void addMethodDesc(final String desc) {
455 addType(Type.getReturnType(desc));
456 Type[] types = Type.getArgumentTypes(desc);
457 for (int i = 0; i < types.length; i++) {
458 addType(types[i]);
459 }
460 }
461
462 protected void addType(final Type t) {
463 switch (t.getSort()) {
464 case Type.ARRAY:
465 addType(t.getElementType());
466 break;
467 case Type.OBJECT:
468 addName(t.getClassName().replace('.', '/'));
469 break;
470 }
471 }
472
473 protected void addSignature(final String signature) {
474 if (signature != null) {
475 new SignatureReader(signature).accept(this);
476 }
477 }
478
479 protected void addTypeSignature(final String signature) {
480 if (signature != null) {
481
482 new SignatureReader(signature).acceptType(this);
483 }
484 }
485
486
487
488
489
490
491
492 public Map<String, Set<MethodCall>> getConstructorCalls() {
493 return constructorCalls;
494 }
495 }