1 package jp.sourceforge.stigmata.birthmarks.wsp;
7 import java.util.ArrayList;
8 import java.util.HashMap;
9 import java.util.Iterator;
10 import java.util.List;
13 import jp.sourceforge.stigmata.Birthmark;
14 import jp.sourceforge.stigmata.BirthmarkContext;
15 import jp.sourceforge.stigmata.BirthmarkElement;
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;
21 import org.objectweb.asm.ClassVisitor;
22 import org.objectweb.asm.ClassWriter;
23 import org.objectweb.asm.Label;
24 import org.objectweb.asm.MethodVisitor;
28 * @author Haruaki Tamada
31 public class StackPatternBasedBirthmarkExtractor extends ASMBirthmarkExtractor{
32 public StackPatternBasedBirthmarkExtractor(BirthmarkSpi service){
37 public BirthmarkExtractVisitor createExtractVisitor(ClassWriter writer, Birthmark birthmark, BirthmarkContext context){
38 return new Visitor(writer, birthmark, context);
42 public ExtractionUnit[] getAcceptableUnits(){
43 return new ExtractionUnit[] {
48 private BirthmarkElement[] buildElement(List<Opcode> opcodes, BirthmarkContext context){
49 StackPattern pattern = buildStackPattern(opcodes, context);
50 List<BirthmarkElement> elements = new ArrayList<BirthmarkElement>();
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();
60 elements.add(new StackPatternBasedBirthmarkElement(subpattern));
62 return elements.toArray(new BirthmarkElement[elements.size()]);
65 @SuppressWarnings("unchecked")
66 private StackPattern buildStackPattern(List<Opcode> opcodes, BirthmarkContext context){
67 Map<Label, Integer> tableMap = new HashMap<Label, Integer>();
68 StackPattern pattern = new StackPattern();
69 Map<Integer, Integer> weights = (Map<Integer, Integer>)context.getProperty("birthmarks.wsp.weights");
72 Integer forwardedStatus = null;
73 for(Opcode opcode: opcodes){
74 opcode.setWeight(weights.get(opcode.getOpcode()));
75 if(opcode.getCategory() == Opcode.Category.TARGETER){
76 forwardedStatus = tableMap.get(((LabelOpcode)opcode).getLabel());
79 if(forwardedStatus == null){
80 currentDepth += opcode.getAct();
83 currentDepth = forwardedStatus + opcode.getAct();
85 forwardedStatus = null;
87 pattern.update(currentDepth, opcode);
88 if(opcode.getCategory() == Opcode.Category.BRANCH){
89 for(Iterator<Label> i = opcode.labels(); i.hasNext(); ){
90 Label label = i.next();
91 tableMap.put(label, currentDepth);
99 private class Visitor extends BirthmarkExtractVisitor{
100 private List<Opcode> opcodeList = new ArrayList<Opcode>();
102 public Visitor(ClassVisitor visitor, Birthmark birthmark, BirthmarkContext context){
103 super(visitor, birthmark, context);
106 public void visitEnd(){
107 BirthmarkElement[] elements = buildElement(opcodeList, getContext());
108 for(BirthmarkElement element: elements){
114 public MethodVisitor visitMethod(int arg0, String arg1, String arg2, String arg3, String[] arg4){
115 MethodVisitor visitor = super.visitMethod(arg0, arg1, arg2, arg3, arg4);
116 OpcodeExtractionMethodVisitor opcodeVisitor = new OpcodeExtractionMethodVisitor(visitor, opcodeList);
118 return opcodeVisitor;