OSDN Git Service

664bb2985d5fdd109ef38986ba4a26323ce47cf7
[stigmata/stigmata.git] / src / main / java / jp / sourceforge / stigmata / birthmarks / cvfv / ConstantValueOfFieldVariableBirthmarkExtractVisitor.java
1 package jp.sourceforge.stigmata.birthmarks.cvfv;
2
3 /*
4  * $Id$
5  */
6
7 import java.util.LinkedHashMap;
8 import java.util.Map;
9
10 import jp.sourceforge.stigmata.Birthmark;
11 import jp.sourceforge.stigmata.BirthmarkContext;
12 import jp.sourceforge.stigmata.birthmarks.BirthmarkExtractVisitor;
13
14 import org.objectweb.asm.ClassVisitor;
15 import org.objectweb.asm.FieldVisitor;
16 import org.objectweb.asm.MethodAdapter;
17 import org.objectweb.asm.MethodVisitor;
18 import org.objectweb.asm.Opcodes;
19 import org.objectweb.asm.Type;
20
21 /**
22  * 
23  * 
24  *
25  * @author Haruaki TAMADA
26  * @version $Revision$ 
27  */
28 public class ConstantValueOfFieldVariableBirthmarkExtractVisitor extends BirthmarkExtractVisitor{
29     private Map<String, TypeAndValueBirthmarkElement> elements = new LinkedHashMap<String, TypeAndValueBirthmarkElement>();
30     private String className;
31
32     public ConstantValueOfFieldVariableBirthmarkExtractVisitor(ClassVisitor visitor, Birthmark birthmark, BirthmarkContext context){
33         super(visitor, birthmark, context);
34     }
35
36     @Override
37     public void visitEnd(){
38         for(String key: elements.keySet()){
39             addElement(elements.get(key));
40         }
41         super.visitEnd();
42     }
43
44     @Override
45     public void visit(int version, int access, String name, String signature,
46                       String superName, String[] interfaces){
47         this.className = name;
48
49         super.visit(version, access, name, signature, superName, interfaces);
50     }
51
52     @Override
53     public FieldVisitor visitField(int access, String name, String desc,
54                                    String signature, Object value){
55
56         FieldVisitor visitor = super.visitField(access, name, desc, signature, value);
57
58         TypeAndValueBirthmarkElement e = elements.get(name);
59         if(e == null){
60             e = new TypeAndValueBirthmarkElement(desc, value);
61         }
62         else{
63             if(value != null){
64                 e.setValue(value);
65             }
66         }
67         elements.put(name, e);
68
69         return visitor;
70     }
71
72     @Override
73     public MethodVisitor visitMethod(int access, String name, String desc, String signature,
74                                      String[] exceptions){
75         MethodVisitor visitor = super.visitMethod(access, name, desc, signature, exceptions);
76
77         if(name.equals("<init>") || name.equals("<clinit>")){
78             visitor = new MethodAdapter(visitor){
79                 private Object constant = null;
80
81                 @Override
82                 public void visitIntInsn(int opcode, int operand){
83                     if(opcode == Opcodes.BIPUSH || opcode == Opcodes.SIPUSH){
84                         constant = new Integer(operand);
85                     }
86                     super.visitIntInsn(opcode, operand);
87                 }
88
89                 @Override
90                 public void visitMethodInsn(int opcode, String owner, String name, String desc){
91                     Type type = Type.getReturnType(desc);
92                     if(!type.equals(Type.VOID_TYPE)){
93                         constant = null;
94                     }
95                     super.visitMethodInsn(opcode, owner, name, desc);
96                 }
97
98                 @Override
99                 public void visitInsn(int opcode){
100                     if(opcode == Opcodes.ICONST_M1)     constant = new Integer(-1);
101                     else if(opcode == Opcodes.ICONST_0) constant = new Integer(0);
102                     else if(opcode == Opcodes.ICONST_1) constant = new Integer(1);
103                     else if(opcode == Opcodes.ICONST_2) constant = new Integer(2);
104                     else if(opcode == Opcodes.ICONST_3) constant = new Integer(3);
105                     else if(opcode == Opcodes.ICONST_4) constant = new Integer(4);
106                     else if(opcode == Opcodes.ICONST_5) constant = new Integer(5);
107                     else if(opcode == Opcodes.LCONST_0) constant = new Long(0L);
108                     else if(opcode == Opcodes.LCONST_1) constant = new Long(1L);
109                     else if(opcode == Opcodes.DCONST_0) constant = new Double(0D);
110                     else if(opcode == Opcodes.DCONST_1) constant = new Double(1D);
111                     else if(opcode == Opcodes.FCONST_0) constant = new Float(0F);
112                     else if(opcode == Opcodes.FCONST_1) constant = new Float(1F);
113                     else if(opcode == Opcodes.FCONST_2) constant = new Float(2F);
114
115                     super.visitInsn(opcode);
116                 }
117
118                 @Override
119                 public void visitLdcInsn(Object object){
120                     constant = object;
121                     super.visitLdcInsn(object);
122                 }
123
124                 @Override
125                 public void visitFieldInsn(int opcode, String owner, String name, String desc){
126                     if(className.equals(owner) && opcode == Opcodes.PUTFIELD){
127                         TypeAndValueBirthmarkElement e = elements.get(name);
128                         if(e == null){
129                             e = new TypeAndValueBirthmarkElement(desc, constant);
130                         }
131
132                         if(e.getValue() == null && constant != null){
133                             if(!checkCast(desc, constant)){
134                                 constant = null;
135                             }
136                             e.setValue(constant);
137                         }
138                     }
139                     super.visitFieldInsn(opcode, owner, name, desc);
140                 }
141             };
142         }
143
144         return visitor;
145     }
146
147     private boolean checkCast(String desc, Object constant){
148         if(constant instanceof Integer){
149             return desc.equals("Ljava/lang/Integer;") ||
150                 desc.equals("I") || desc.equals("S") || desc.equals("Z") ||
151                 desc.equals("C") || desc.equals("B");
152         }
153         else if(constant instanceof Float){
154             return desc.equals("Ljava/lang/Float;") || desc.equals("F");
155         }
156         else if(constant instanceof Double){
157             return desc.equals("Ljava/lang/Double;") || desc.equals("D");
158         }
159         else if(constant instanceof Long){
160             return desc.equals("Ljava/lang/Long;") || desc.equals("J");
161         }
162         else if(constant instanceof String){
163             return desc.equals("Ljava/lang/String;");
164         }
165         return false;
166     }
167 }