OSDN Git Service

daily commit
[stigmata/stigmata-plugins.git] / wsp / src / main / java / jp / sourceforge / stigmata / birthmarks / wsp / StackPatternBasedBirthmarkExtractor.java
1 package jp.sourceforge.stigmata.birthmarks.wsp;
2
3 /*
4  * $Id$
5  */
6
7 import java.util.ArrayList;
8 import java.util.HashMap;
9 import java.util.Iterator;
10 import java.util.List;
11 import java.util.Map;
12
13 import jp.sourceforge.stigmata.Birthmark;
14 import jp.sourceforge.stigmata.BirthmarkElement;
15 import jp.sourceforge.stigmata.BirthmarkEnvironment;
16 import jp.sourceforge.stigmata.ExtractionUnit;
17 import jp.sourceforge.stigmata.birthmarks.ASMBirthmarkExtractor;
18 import jp.sourceforge.stigmata.birthmarks.BirthmarkExtractVisitor;
19 import jp.sourceforge.stigmata.spi.BirthmarkSpi;
20
21 import org.objectweb.asm.ClassVisitor;
22 import org.objectweb.asm.ClassWriter;
23 import org.objectweb.asm.Label;
24 import org.objectweb.asm.MethodVisitor;
25
26 /**
27  * 
28  * @author Haruaki Tamada
29  * @version $Revision$
30  */
31 public class StackPatternBasedBirthmarkExtractor extends ASMBirthmarkExtractor{
32     public StackPatternBasedBirthmarkExtractor(BirthmarkSpi service){
33         super(service);
34     }
35
36     @Override
37     public BirthmarkExtractVisitor createExtractVisitor(ClassWriter writer, Birthmark birthmark, BirthmarkEnvironment environment){
38         return new Visitor(writer, birthmark, environment);
39     }
40
41     @Override
42     public ExtractionUnit[] getAcceptableUnits(){
43         return new ExtractionUnit[] {
44             ExtractionUnit.ARCHIVE, ExtractionUnit.PACKAGE, ExtractionUnit.CLASS,
45         };
46     }
47
48     private BirthmarkElement[] buildElement(List<Opcode> opcodes){
49         StackPattern pattern = buildStackPattern(opcodes);
50         List<BirthmarkElement> elements = new ArrayList<BirthmarkElement>();
51
52         StackPattern subpattern = new StackPattern();
53         for(CurrentDepth depth: pattern){
54             subpattern.update(depth);
55             if(depth.getDepth() == 0){
56                 elements.add(new StackPatternBasedBirthmarkElement(subpattern));
57                 subpattern = new StackPattern();
58             }
59         }
60         elements.add(new StackPatternBasedBirthmarkElement(subpattern));
61
62         return elements.toArray(new BirthmarkElement[elements.size()]);
63     }
64
65     private StackPattern buildStackPattern(List<Opcode> opcodes){ 
66         Map<Label, Integer> tableMap = new HashMap<Label, Integer>();
67         StackPattern pattern = new StackPattern();
68
69         int currentDepth = 0;
70         Integer forwardedStatus = null;
71         for(Opcode opcode: opcodes){
72             if(opcode.getCategory() == Opcode.Category.TARGETER){
73                 forwardedStatus = tableMap.get(((LabelOpcode)opcode).getLabel());
74             }
75             else{
76                 if(forwardedStatus == null){
77                     currentDepth += opcode.getAct();
78                 }
79                 else{
80                     currentDepth = forwardedStatus + opcode.getAct(); 
81                 }
82                 forwardedStatus = null;
83
84                 pattern.update(currentDepth, opcode);
85                 if(opcode.getCategory() == Opcode.Category.BRANCH){
86                     for(Iterator<Label> i = opcode.labels(); i.hasNext(); ){
87                         Label label = i.next();
88                         tableMap.put(label, currentDepth);
89                     }
90                 }
91             }
92         }
93         return pattern;
94     }
95
96     private class Visitor extends BirthmarkExtractVisitor{
97         private List<Opcode> opcodeList = new ArrayList<Opcode>();
98
99         public Visitor(ClassVisitor visitor, Birthmark birthmark, BirthmarkEnvironment environment){
100             super(visitor, birthmark, environment);
101         }
102
103         public void visitEnd(){
104             BirthmarkElement[] elements = buildElement(opcodeList);
105             for(BirthmarkElement element: elements){
106                 addElement(element);
107             }
108         }
109
110         @Override
111         public MethodVisitor visitMethod(int arg0, String arg1, String arg2, String arg3, String[] arg4){
112             MethodVisitor visitor = super.visitMethod(arg0, arg1, arg2, arg3, arg4);
113             OpcodeExtractionMethodVisitor opcodeVisitor = new OpcodeExtractionMethodVisitor(visitor, opcodeList);
114
115             return opcodeVisitor;
116         }
117     };
118
119
120 }