1
2
3
4 package org.softevo.jdynpur.runtime;
5
6
7 import org.objectweb.asm.ClassAdapter;
8 import org.objectweb.asm.ClassVisitor;
9 import org.objectweb.asm.MethodVisitor;
10 import org.objectweb.asm.Opcodes;
11 import org.softevo.util.ObjectIdMapper;
12 import org.softevo.util.asm.FieldIdentifier;
13 import org.softevo.util.asm.MethodIdentifier;
14 import org.softevo.util.asm.MethodIdentifierMapGenerator;
15
16 public class InstrumentingClassFileTransformer extends ClassAdapter implements Opcodes {
17
18 private MethodIdentifierMapGenerator identifierMapGenerator = null;
19
20 private String className = null;
21
22 private String superClassName = null;
23
24 private boolean isInterface = false;
25
26 private ObjectIdMapper<FieldIdentifier> fieldIdentifierMap;
27
28 private boolean traceParameterMutability;
29
30 public InstrumentingClassFileTransformer(ClassVisitor classVisitor, String className,
31 MethodIdentifierMapGenerator identifierMapGenerator, ObjectIdMapper<FieldIdentifier> fieldIdentifierMap,
32 boolean traceParameterMutability) {
33 super(classVisitor);
34 this.identifierMapGenerator = identifierMapGenerator;
35 this.className = className;
36 this.fieldIdentifierMap = fieldIdentifierMap;
37 this.traceParameterMutability = traceParameterMutability;
38 }
39
40 @Override
41 public void visit(int version, int access, String name, String signature, String superName, String[] interfaces) {
42 super.visit(version, access, name, signature, superName, interfaces);
43 this.superClassName = superName;
44 if ((access & ACC_INTERFACE) > 0) {
45 isInterface = true;
46 }
47 }
48
49 @Override
50 public MethodVisitor visitMethod(int access, String methodName, String desc, String signature, String[] exceptions) {
51 MethodVisitor writingMethodVisitor;
52 MethodStartEndTracingVisitor startEndVisitor;
53 ArrayTracingVisitor arrayTracingVisitor;
54 ObjectCreationTracingVisitor objectCreationVisitor;
55 FieldWriteTracingVisitor fieldWriteVisitor;
56 ConstructorPurityTracingVisitor constructorVisitor;
57 ParameterTracingVisitor parameterTracingVisitor;
58 int methodIdentifier;
59
60 if (!isInterface && ((access & ACC_ABSTRACT) == 0) && ((access & ACC_NATIVE) == 0)) {
61 methodIdentifier = identifierMapGenerator.getIdentifier(className, methodName, desc, access);
62 MethodIdentifier methodId = identifierMapGenerator.getMethodIdentifier(methodIdentifier);
63 writingMethodVisitor = super.visitMethod(access, methodName, desc, signature, exceptions);
64 startEndVisitor = new MethodStartEndTracingVisitor(writingMethodVisitor, access, className,methodName, desc,
65 methodIdentifier);
66 if (traceParameterMutability) {
67 parameterTracingVisitor = new ParameterTracingVisitor(startEndVisitor, methodId, superClassName);
68 arrayTracingVisitor = new ArrayTracingVisitor(parameterTracingVisitor, access, desc);
69 } else {
70 arrayTracingVisitor = new ArrayTracingVisitor(startEndVisitor, access, desc);
71 }
72 objectCreationVisitor = new ObjectCreationTracingVisitor(arrayTracingVisitor);
73 fieldWriteVisitor = new FieldWriteTracingVisitor(objectCreationVisitor, methodName, className, superClassName, fieldIdentifierMap);
74 constructorVisitor = new ConstructorPurityTracingVisitor(fieldWriteVisitor, methodName, className, superClassName);
75 return constructorVisitor;
76 } else {
77 return super.visitMethod(access, methodName, desc, signature, exceptions);
78 }
79 }
80
81 public MethodIdentifierMapGenerator getIdentifierMapGenerator() {
82 return identifierMapGenerator;
83 }
84
85 public void setIdentifierMapGenerator(MethodIdentifierMapGenerator identifierMapGenerator) {
86 this.identifierMapGenerator = identifierMapGenerator;
87 }
88
89 }