com.retroduction.carma.transformer.asm.AbstractASMTransition.java Source code

Java tutorial

Introduction

Here is the source code for com.retroduction.carma.transformer.asm.AbstractASMTransition.java

Source

/**
  *  This file is part of Carma (Retroduction.org).
  *
  *  Carma is free software: you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
  *  the Free Software Foundation, either version 3 of the License, or
  *  (at your option) any later version.
  *
  *  Carma is distributed in the hope that it will be useful,
  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  *  GNU General Public License for more details.
  *
  *  You should have received a copy of the GNU General Public License
  *  along with Carma.  If not, see <http://www.gnu.org/licenses/>.
  *
  * Copyright Retroduction.org (c) 2007-2010
  */

package com.retroduction.carma.transformer.asm;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

import org.objectweb.asm.Attribute;
import org.objectweb.asm.ClassReader;
import org.objectweb.asm.tree.AbstractInsnNode;
import org.objectweb.asm.tree.ClassNode;
import org.objectweb.asm.tree.LabelNode;
import org.objectweb.asm.tree.LineNumberNode;
import org.objectweb.asm.tree.MethodNode;

import com.retroduction.carma.core.api.testrunners.om.Mutant;
import com.retroduction.carma.core.api.transitions.ITransition;
import com.retroduction.carma.transformer.CRTEntry;
import com.retroduction.carma.transformer.CharacterRangeTable;

/**
 * 
 * Abstract mutation transformation processing class. Does the common traversing
 * logic over the byte code.
 * 
 * @author arau
 * 
 * TODO: arau: should be implemented using delegation instead of inheritance.
 * 
 */
public abstract class AbstractASMTransition implements ITransition {

    public List<Mutant> applyTransitions(byte[] byteCode) {

        ClassNode classNode = new ClassNode();

        ClassReader reader = new ClassReader(byteCode);

        reader.accept(classNode, new Attribute[] { new CharacterRangeTable() }, 0);

        List<Mutant> result = new ArrayList<Mutant>();

        int methodIndex = 0;

        for (MethodNode methodNode : (List<MethodNode>) classNode.methods) {

            Iterator<AbstractInsnNode> instructionIterator = methodNode.instructions.iterator();

            CharacterRangeTable crt = null;

            if (methodNode.attrs != null) {
                for (Attribute attr : (List<Attribute>) methodNode.attrs) {
                    if (attr instanceof CharacterRangeTable) {
                        crt = (CharacterRangeTable) attr;
                    }
                }
            }

            CRTEntry crtEntry = new CRTEntry();

            while (instructionIterator.hasNext()) {

                AbstractInsnNode node = instructionIterator.next();

                if (node instanceof LineNumberNode) {
                    if (crt == null) {
                        crtEntry.setStartPos(((LineNumberNode) node).line << 10);
                        crtEntry.setEndPos(((LineNumberNode) node).line << 10);
                    }
                    continue;
                }

                if ((node instanceof LabelNode)) {

                    if (crt == null)
                        continue;

                    if (crt.getLabelOffsets().containsKey(((LabelNode) node).getLabel())) {
                        crtEntry = crt.getLabelOffsets().get(((LabelNode) node).getLabel());
                    }
                    continue;
                }

                this.checkNode(classNode, methodNode, result, crtEntry, node);

            }
            methodIndex++;

        }

        return result;
    }

    protected abstract void checkNode(ClassNode classNode, MethodNode methodNode, List<Mutant> result,
            CRTEntry jcovInfo, AbstractInsnNode node);

}